C++ const对象的构造

C++ const对象的构造,c++,constructor,constants,C++,Constructor,Constants,C++11§12.1/14: 在const对象的构造过程中,如果对象或其任何子对象的值是通过 不是直接或间接从构造器的 指针,则获取对象或子对象的值 未指明。[示例: structc; 无效无选择(C*); 结构C{ INTC; C():C(0){no_opt(this);} }; 常数C-cobj; 无效无选项(C*cptr){ //未指定cobj.c的值 int i=cobj.c*100; cptr->c=1; //未指定cobj.c的值 cout真正的const对象可能被编译器视为合法常量

C++11§12.1/14:

在const对象的构造过程中,如果对象或其任何子对象的值是通过 不是直接或间接从构造器的 指针,则获取对象或子对象的值 未指明。[示例:

structc;
无效无选择(C*);
结构C{
INTC;
C():C(0){no_opt(this);}
};
常数C-cobj;
无效无选项(C*cptr){
//未指定cobj.c的值
int i=cobj.c*100;
cptr->c=1;
//未指定cobj.c的值

cout真正的
const
对象可能被编译器视为合法常量。它可以假定它们的值永远不会改变,甚至将它们存储在
const
内存中,例如ROM或闪存。因此,只要对象实际上不是常量,您就需要使用
this
提供的非常量访问路径。这种情况仅在对象构造和破坏期间存在

顺便说一句,我认为不需要对析构函数有相应的要求,因为对象生命周期已经结束,
cobj.c
的析构函数一开始就不可访问

正如Matthieu所提到的,在构建或销毁过程中,除了通过
这个
访问对象之外,访问对象是一种强烈的“代码气味”。回顾C++11§3.8[基本生活]^1和6中,构造函数中的
cobj.c
似乎是UB,原因与它在析构函数中的原因相同,而不管对象是
const
或§12.1/14,因为它的生命周期直到初始化完成才开始(构造函数返回)


它可能会起作用,但它会为优秀的C++程序员敲响警钟,而这本书是非法的。< /P> < P>规则的原因是允许编译器作出。 基于对象常量的优化。例如, 根据优化的不同,编译器可能会替换第二个

cobj.c*100
in
no_opt
with
i
。更可能的情况是,在这种情况下 在这种情况下,优化器将抑制
i
及其初始化 完全正确,因此代码看起来会工作。但这可能不是 如果您在更改
cptr->c
之前还输出了
i
,则视情况而定 编译器优化的力度。但允许编译器 假设
*cptr
不是
cobj
的别名,因为
cobj
是 const对象,当您通过
*cptr
进行修改时,它不能指向 没有未定义行为的常量对象

当然,如果对象不是const,那么问题就不会发生 编译器必须始终考虑到
*cptr
cobj

我要注意的是,在上面的例子中,
cobj.c
cobj
完全构造之前就被访问了。在我看来,即使对于非常量对象,这个操作也是可疑的。@MatthieuM.Why?在我看来是有效的(即使您向struct c添加了基类)@VJovic:只要构造函数还没有运行,对象就还没有激活——请看Sutter的介绍。如果对象还没有激活,访问它是可疑的。我并不是说它一定没有定义或未指定,只是说它“闻起来很难闻”。我不理解它的措辞。
cptr
是从
这个
中获得的,但引用中说“未获得”(如何获得)?此外,此引号意味着构造函数主体不得修改任何成员,否则const对象的行为将不确定?@visitor:问题是在构造函数返回之前使用
cobj
。读取访问是有问题的。
C():C(0){C=1;}
-那么你的意思是这也是无效的?这似乎离题了:它没有解决
cobj.c
c
的构造函数运行期间(即使在初始化的列表运行之后)有一个未指定的值这一事实。它也没有解决行为不同的原因(在这方面)在常量对象和非常量对象之间。@MatthieuM。我想我已经讨论了这两个问题。问题是编译器可以识别
cobj.c
访问路径具有无法更改的值。无论哪个函数访问它,没有常量值的
const
对象都是禁止的。啊,我终于得到了什么你刚才说的是“非常量访问路径”,很抱歉太密集了。
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';
}