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++程序员敲响警钟,并且从书上看这是非法的。

09-10 06:29
查看更多