You Don't Know const and mutable -- Herb Sutter

In August, Herb Sutter gave a brand new 30-min talk at C++ and Beyond where he laid out the fundamentally new meanings of two long-time C++ keywords:

You Don't Know [const] and [mutable]

Herb Sutter

There’s a major change in C++11 that [...] rewrites pre-C++11 design guidance and is directly related to writing solid code in a concurrent and parallel world. And it isn’t just academic — everyone is going to have to learn and apply the new C++11 guidance that we’ll cover in this session.

This is a great example of how C++11 is a simpler language: We can stop the Cold War-era waffling about subtleties about what 20th-century C++ const means, and proudly declare modern C++ const has the simple and natural and "obvious" meaning that most people expected all along anyway.

One of the most common questions after the talk was, "Do other C++ experts agree with Herb's conclusions?" The answer is yes -- regarding his upcoming The C++ Programming Language, Fourth Edition, Bjarne Stroustrup writes: "I do point out that const means immutable and absence of race conditions in the last Tour chapter. I plan more for the concurrency chapter." Look for the third Tour chapter to be posted here next week, and the aforementioned last Tour chapter to be posted here in early February.

Enjoy.

Add a Comment

Comments are closed.

Comments (6)

0 1

snkkid said on Jan 1, 2013 09:29 AM:

I don't see how you can guarantee thread-safety if constant member functions can still have implicit side-effects such as modifying completely unrelated state like global variables or class static variables.

I also can not see anything different about the mutable keyword except just warping your view of them in the context of concurrency, you can still mark any data member you want as mutable like a non-atomic integer right?




1 0

H Sutter said on Jan 1, 2013 10:18 AM:

@snkkid: Yes, you can write a data race on a global in any mainstream language.

What this means is that if you write const on a member function then the function really must not have side effects, and if you violate that then you wrote a bug. In C++11, const means thread-safe == "immutable or internally synchronized." See also Bjarne's note above -- this is real, not theoretical or abstract.

Corollary (as explained in the talk): mutable isn't warped, it has always meant "already logically const." Applying the new axiom s/const/thread-safe/, that now means "already logically thread-safe" == "immutable or internally synchronized."

But don't try it on paper. Try in it real code with synchronization, and you'll quickly see that member variables just want to be mutable for the reasons I gave. And if you need more reasons, there's another C&B talk to go live soon with additional examples because they really do just come up naturally -- watch for them in the talk "atomic<> Weapons: The C++11 Memory Model and Modern Hardware" coming fairly soon.
1 0

snkkid said on Jan 1, 2013 11:17 AM:

@Herb Thanks for responding, i was hoping you would catch my comment and reply.

"What this means is that if you write const on a member function then the function really must not have side effects, and if you violate that then you wrote a bug."

If constant member functions must not have side-effects like true referentially transparent functions why not make this enforced in the language so the compiler enforces this semantic at compile-time and thus give compile errors instead of leaving this a source of potential run-time bugs. Well I think the reason why this isn't possible is because of breaking preexisting code bases.

So it is a shame that with the additions of standardized attribute system, standardized const/pure attributes were not proposed/added to the spec like const/pure attributes in gcc or some other mechanism for new code.

Take it further and allow specifying free functions as being referentially transparent.

This would have many benefits, compiler enforced, self-documenting code where programmers can know from a glance that the function they are looking is to be guaranteed thread-safe.

We do have something close to this, generalized constant expressions.

> In C++11, const means thread-safe == "immutable or internally synchronized." >See also Bjarne's note above -- this is real, not theoretical or abstract.

I think it would be more fair to say that this is a promise not necessarily a guarantee (except for the case of intrinsic/primitive/atomic data-types). Without more changes to the definition of const or new language features/attributes one can not simply glance at constant member function declaration and assume the function to be 100% thread-safe and/or re-entrant because this can be violated by using unsynchronized data members marked as mutable or modifying unsynchronized non-data members.

I do know what you're saying that in most cases in real code bases, mutable keyword is often used with mutex locks and data-members which aren't really part of the logical state. However there are also typical cases in existing code-bases where mutable is used for unsynchrnoized data members like caches (which may or may not use standard library containers) and dirty flags for lazy evaluation.

I think what is being said about const/mutable in C++11 has be said carefully and with foot-notes otherwise it will lead to miss-understanding to C++ programmers who don't have much experience writing concurrent/parallel code.

Many C++ programmers would love to be able to truly specify referentially transparent functions of any kind be it member function or free-function.

0 0

snkkid said on Jan 1, 2013 11:34 AM:

I'm sorry for the formatting of my previous comment, I tried to add spacing between paragraphs and quotes but they did not come out correctly.
0 0

H Sutter said on Jan 1, 2013 11:53 AM:

@snkkid: NP, we're working on the comment formatting and you'll see improvements soon.
1 0

Andy Prowl said on Jan 2, 2013 06:24 PM:

@Herb: Thank you for the great talk, of course I agree with the fact that const should mean "thread safe". However, I do not see how this is implied by the current standard.

If I got it right, the whole point is: "inside a const function you can modify a mutable variable, as long as you do that atomically (i.e. with proper synchronization)". However, [17.6.5.9/3] says that an STL function "shall not directly or indirectly *modify* objects" by (among other things) calling any of their const member functions (this is my deduction). But since those const member functions are allowed to modify mutable variables (provided they do so in a thread-safe manner), this means that modifying a mutable variable in a thread-safe manner is not seen as a "modify" per [17.6.5.9/3]. Why is this so? I cannot find where this is stated in the standard.

I think [17.6.5.9/3] should rather say "shall not directly or indirectly *introduce data races*". I realize that after "shall not directly or indirectly *modify* objects" it mentions paragraph (1.10), but paragraph 1.10 (especially relevant is 1.10.4) just defines what a data race is; it says there is no data race if every modify is atomic, but it does not say that an atomic modify is not a modify.

I hope I made my point clear enough. Am I missing something?