g ++中奇怪的C++构造函数/拷贝构造函数问题
#include <iostream>
using namespace std;
class X {
public:
X() {
cout<<"Cons"<<endl;
}
X(const X& x){
cout<<"Copy"<<endl;
}
void operator=(const X& x){
cout<<"Assignment called";
}
};
X& fun() {
X s;
return s;
}
int main(){
X s = fun();
return 0;
}
这段代码也调用了拷贝构造函数。为什么这个工作?我记得我第一次运行这个程序时,它陷入了故障。但过了一段时间,它开始称这个副本缺点。现在工作!奇怪的。g ++中奇怪的C++构造函数/拷贝构造函数问题
但是如果我更换,乐趣()如下:
X fun() {
X s;
return s;
}
然后复制利弊。不叫。我认为副本缺点。在这种情况下会被调用。但正如@ flyfishr64指出的那样,RVO即将在这里发挥作用。但它仍不能解释我返回参考的情况。我认为它应该总是段错误。
任何解释?
为了扩大对@ flyfishr64的回答
复制构造函数调用这里,因为这:
X s = fun();
是初始化。您正在使用fun()来构造对象,而不是调用默认的构造函数。它相当于:
X s(fun());
您看到打印出的“缺点”是针对fun()中的实例。看到这篇文章:Assignment operator in C++了解更多。
在此代码:
X fun() {
X s;
return s;
}
拷贝构造函数是没有得到所谓,因为返回值优化,让编译器旁路创建本地变量“s”和直接在返回的变量构建X 。
你可以阅读更多关于RVO here
这将返回引用堆栈对象不一旦方法返回存在 - 堆栈unwinded,记忆依然存在,但如果把它修改成你不应该使用它
X& fun() {
X s;
return s;
}
:
X fun() {
X s;
return s;
}
您现在正在返回副本。如果编译器非常聪明,它可能会做:
X fun() {
return X();
}
在这种情况下,X
在来电直接分配的堆栈,因此不需要该副本。
如果它segfault或不取决于如果您访问无效的内存。
在您的示例中,您不访问结构中的任何值。要查看段错误,请首先保留一个引用,您返回的fun()
将一些变量添加到结构X
中,并在从fun()
返回后调用另一种在内部分配堆内存的方法(这应该覆盖在fun
中使用的原始内存)堆栈中的值(最好是0)。在此第二种方法返回后,尝试使用从fun
返回的原始参考打印出X
的值...
当您返回对此类局部变量的引用时,您正在调用未定义的行为。
它恰好在这种情况下工作,因为class X
的函数都没有使用this
指针,所以无关紧要,它不再有效。
仅仅返回这样的引用调用UB?你有参考吗? – 2010-01-28 13:55:48
你不能只说“但过了一段时间,它开始称这个副本缺点,现在工作!!” - 你一定改变了一些东西。 – Smashery 2009-11-27 04:33:08
没有。我做的唯一的事情是添加1 cout,然后删除它。 – user855 2009-11-27 04:35:17
很有可能。因为当我尝试以下时,复制构造函数未被调用。 X&fun(){X s;返回s; } int main(){X&x = fun();返回0; } 但是用这个理论,是不是不意味着返回局部变量的引用总是有效的?因为如果我在主窗口中执行X s = fun(),那么拷贝构造函数无论如何都会被调用? – user855 2009-11-27 04:45:40