C++ 11§12.1/14:
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
。我的问题是,为什么在进入构造函数之前将初始化列表将其设置为cobj.c
时,应未指定0
的值?如果使用非常量对象,此行为有何不同? 最佳答案
真正const
对象可以被编译器视为合法常量。它可以假定它们的值永不更改,甚至可以将它们存储在const
内存中,例如ROM或闪存。因此,只要对象实际上不是常量,就需要使用this
提供的非常量访问路径。此条件仅在对象构建和销毁期间存在。
暂时,我认为对析构函数没有相应的要求,因为对象生存期已经结束,并且一旦cobj.c
的析构函数开始,就无法访问cobj
。
正如Matthieu提到的那样,在构造或销毁过程中,除了通过this
之外,还可以通过cobj.c
访问对象,这是一种强烈的“代码气味”。回顾C++ 11§3.8[basic.life]¶1和6,似乎构造器内部的const
是UB,其原因与析构函数内部的原因相同,无论对象是ojit_code还是§12.1/14,因为它的生命周期直到初始化完成(构造函数返回)后才开始。
它可能会起作用,但是它会为优秀的C++程序员敲响警钟,并且从书上看这是非法的。