Is a constexpr more “constant” than const?

2019-04-20 05:50发布

问题:

The C++ Programming Language Fourth Edition - Bjarne Stroustrup: (emphasis mine)

2.2.3. Constants

In a few places, constant expressions are required by language rules (e.g., array bounds (§2.2.5, §7.3), case labels (§2.2.4, §9.4.2), some template arguments (§25.2), and constants declared using constexpr). In other cases, compile-time evaluation is important for performance. Independently of performance issues, the notion of immutability (of an object with an unchangeable state) is an important design concern (§10.4).

It seems that Stroustrup is suggesting here that constexpr ensures immutability of an object better than a traditional const declaration. Is this correct? Are there ways in which constexpr can be more secure/less volatile than const, or does Stroustrup simply mean that since there are ways to use constexpr that are not supported with const (see Is constexpr really needed?), in those cases immutability can be ensured using constexpr?

回答1:

He states in the beginning of the section:

C++ supports two notions of immutability

and he lists const and constexpr, I don't believe he is attempting to say that constexpr ensures immutability better than const they just have different features, although I admit the fact the sentence cites section 10.4 Constant Expressions does seem to imply that, that interpretation is inconsistent with the rest of the text.

A variable that is const is immutable in that scope but may not be const in the larger scope(for example a const reference parameter to a function) and that is perhaps a subtle distinction he is attempting to make, he says that const:

is used primarily to specify interfaces

whereas constexpr:

This is used primarily to specify constants, to allow placement of data in read-only memory

Any variable that is constexpr should be evaluated at compile time and thus usable where constant expressions are required whereas a variable that is passed as const to a function does not have to be const outside that scope.

Sure you can cast away constness using const_cast but attempting to modify a const object is undefined behavior and so it is no less immutable than constexpr in that sense, from the draft C++11 standard section 7.1.6.1 The cv-qualifiers:

any attempt to modify a const object during its lifetime (3.8) results in undefined behavior

Jonathan Wakely notes that a constexpr variable like const variables can have a mutable member but that member can not be used in a constant expression.

Note that a constexpr variable is also const, from the draft C++11 standard section 7.1.5 The constexpr specifier:

A constexpr specifier used in an object declaration declares the object as const.



回答2:

const dosn't ensure bitwise constness, e.g. as classes can have mutable members (typical example would be a private mutex for internal synchronization) and you can const_cast away the constness from a pointer.

constexpr declares a constant variable or function that can be calculated at compile time, which implies some restrictions on what the object can be, but I believe, the keyword itself doesn't provide any additional guarantees during runtime compared to const. See also this discussion.