我对C ++中的引用有一些疑问。
Test & returnref(){
Test obj(9,9);
cout << "in function: " << &obj << endl;
return obj;
} // *
int main(){
Test & asdf = returnref();
Test asdf2 = returnref();
cout << "in main asdf: " << &asdf;
cout << "in main asdf2: " << &asdf2;
cin.get();
return 0;
}
结果:
in function: 0033F854
in function: 0033F854
in main asdf: 0033F854
in main asdf2: 0033F938
是对的吗? 在我看来,obj正在第5行被删除(*) - 因为它在这个函数范围内是活的。 为什么它的工作原理?它只是Visual Studio吗?或者我错了?
答案 0 :(得分:3)
答案 1 :(得分:1)
使用对函数返回的局部变量的引用具有未定义的行为。但请注意,ub并不意味着“它会崩溃”,意思是“我不知道会发生什么”。
在您的情况下,您的调用不会重复使用该堆栈所使用的内存,因此您的局部变量仍然存在。
答案 2 :(得分:1)
您的选择是按值返回或返回基于堆的对象的引用/指针。
将您的功能签名更改为此
Test returnval()
将复制obj
。请注意,打印出的指针对于类中的对象和外部对象可能仍具有相同的值,因为编译器可能已执行return value optimisation。
如果Test
类不管理动态分配的资源,那么您可以依赖编译器将注入的自动创建的复制构造函数。如果Test
已动态分配数据,那么您必须编写自己的数据。请参阅What is the Rule of Three?。
您可以使用new
将其更改为基于堆的对象,然后返回指针:
Test* returnptr(){
Test* obj = new Test(9,9);
cout << "in function: " << obj << endl;
return obj;
}
或者更好的是,像shared_ptr这样的智能指针可以为您管理删除:
shared_ptr<Test> returnptr() {
// Wrapping the pointer in a shared_ptr will ensure it gets cleaned
// up automatically when the last reference to it (usage of it)
// goes out of scope.
shared_ptr<Test> obj(new Test(9,9));
cout << "in function: " << obj.get() << endl;
return obj;
}
正如我的回答中的一位评论者所指出的,在C ++ 11中,您还可以通过为Test
提供移动构造函数并使用{{}来控制函数中临时对象的返回方式。必要时1}}这是一个相当多的主题,但您可以通过以下链接阅读更多相关信息: