C++ 是自初始化';A=A';允许?
此代码在复制构造函数中运行时失败。C++ 是自初始化';A=A';允许?,c++,C++,此代码在复制构造函数中运行时失败。 但是编译器(MSVS2008)没有发出警告 你能解释一下(最好是引用标准)这个代码是非法的还是什么 我知道A=A;从一开始就不应该写, 但我在寻找一个理论背景 class A { public: A() :p(new int) { } A(const A& rv) { p = new int(*rv.p); } ~A() { delet
但是编译器(MSVS2008)没有发出警告 你能解释一下(最好是引用标准)这个代码是非法的还是什么 我知道A=A;从一开始就不应该写, 但我在寻找一个理论背景
class A
{
public:
A()
:p(new int)
{
}
A(const A& rv)
{
p = new int(*rv.p);
}
~A()
{
delete p;
}
private:
int *p;
};
int main()
{
A a = a;
}
您的代码调用的不是标准构造函数,而是复制构造函数,因此您正在访问未初始化的指针。
A=A代码>绝对不应该被编写。但是a=a
是可以写的。分配操作员必须检查&rv==此
,如果是自复制,则不执行任何操作
哦,是的,您确实需要为类A编写赋值运算符。根据标准(12.6.1[class.expl.init]),自初始化是完全合法的
因此,以下内容是合法的
A a = a;
您只需要编写副本构造函数来正确处理它
A(const A& rv)
{
if(&rv == this) {
p = new int(0);
return;
}
p = new int(*rv.p);
}
编辑:根据注释更新代码。关于自我分配的有趣阅读:
特别是,请注意与此问题相关的“Postscript#1”以及给出的一些答案。标准中是否引用了关于这是否是编译时错误的内容?它确实不可能是编译时错误。以下是触发问题的两个条件:*复制构造函数从源对象取消引用指针。*您正在用对象本身初始化对象。这两个问题可能位于完全不同的编译单元中,编译器需要同时看到这两个条件才能标记错误。每个条件本身都不是问题,因此编译器没有理由抱怨。@JohnMcG:I disaggre。。。变量声明和初始化不能在不同的编译单元中。这显然没有任何意义。不幸的是,C++委员会从来没有想过这个问题(或者说它并不重要……)。你可以争辩说,编译器是标准共模的,你在这个问题上是对的,但我认为这是标准的一个错误。对不起,我现在已经修复了答案。不。赋值操作符可以被优化掉,取而代之的是复制构造;a=a?将调用的默认构造函数,然后调用::运算符=()。我怀疑它会被优化掉。Martin的观点是,检查赋值操作符中的自赋值可能是防止类似情况发生的必要条件,但这是不够的。因为分配可以优化到复制构造函数中,所以复制构造函数也需要考虑。好吧,“正确”-这取决于你的意图。这样,您将得到未初始化的对象。请记住,“a”在作为参数传递给其自己的副本构造函数时不会初始化。因此“A::p”是未定义的,此复制构造函数不会对其进行初始化。补充:关于标准的答复的第一部分是正确的,但我认为第二部分是可疑的。虽然在这里可以避免崩溃,但由于p未初始化,以后很可能会崩溃。更新了复制构造函数代码以将p初始化为有用的内容检查自复制仅在运算符=()中有意义,而在复制构造函数中没有意义。请看Fred Larson的答案。正如我从答案中了解到的,该代码是合法的。我应该添加一个断言还是如果(&rv==this)p=NULL;为了安全起见?有人在他们的代码中以任何方式处理这个问题吗?