C++11 §12.1/14:
During the construction of a const object, if the value of the object or any of its subobjects is accessed through an lvalue that is not obtained, directly or indirectly, from the constructor’s this pointer, the value of the object or subobject thus obtained is unspecified. [Example:
struct C;
void no_opt(C*);
struct C {
int c;
C() : c(0) { no_opt(this); }
};
const C cobj;
void no_opt(C* cptr) {
// value of cobj.c is unspecified
int i = cobj.c * 100;
cptr->c = 1;
// value of cobj.c is unspecified
cout << cobj.c * 100 << '\n';
}
编译上面的例子输出100
。我的问题是为什么在进入构造函数之前初始化列表将其设置为 0
时应该未指定 cobj.c
的值?如果使用非常量对象,这种行为有何不同?
最佳答案
真正的 const
对象可以被编译器视为合法的常量。它可以假设它们的值永远不会改变甚至将它们存储在 const
内存中,例如ROM 或闪存。因此,您需要使用 this
提供的非常量访问路径,只要对象实际上不是常量即可。这种情况只存在于对象的构造和销毁过程中。
顺便说一句,我认为不需要对析构函数有相应的要求,因为对象的生命周期已经结束,并且 cobj.c
是不可访问的,因为 cobj
开始。
正如 Matthieu 所提到的,在构造或销毁期间通过 this
访问对象是一种强烈的“代码气味”。回顾 C++11 §3.8 [basic.life] ¶1 和 6,构造函数内部的 cobj.c
似乎是 UB,原因与它在析构函数内部的原因相同,无论对象如何是 const
或 §12.1/14,因为它的生命周期直到初始化完成(构造函数返回)才开始。
它可能会起作用,但它会给优秀的 C++ 程序员敲响警钟,而且从书上看它是非法的。
关于c++ - const对象的构造,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8738929/