我很难理解在 C++ 中返回值背后的真正作用。
让我们有以下代码:
class MyClass {
public:
int id;
MyClass(int id) {
this->id = id;
cout << "[" << id << "] MyClass::ctor\n";
}
MyClass(const MyClass& other) {
cout << "[" << id << "] MyClass::ctor&\n";
}
~MyClass() {
cout << "[" << id << "] MyClass::dtor\n";
}
MyClass& operator=(const MyClass& r) {
cout << "[" << id << "] MyClass::operator=\n";
return *this;
}
};
MyClass foo() {
MyClass c(111);
return c;
}
MyClass& bar() {
MyClass c(222);
return c;
}
MyClass* baz() {
MyClass* c = new MyClass(333);
return c;
}
我使用 gcc 4.7.3。
情况1
当我打电话时:
MyClass c1 = foo();
cout << c1.id << endl;
输出是:
[111] MyClass::ctor
111
[111] MyClass::dtor
我的理解是 in foo
object 在堆栈上创建,然后在 return 语句时销毁,因为它是范围的结尾。返回是通过对象复制(复制构造函数)完成的,该对象复制稍后c1
在 main(赋值运算符)中分配。如果我是对的,为什么复制构造函数和赋值运算符都没有输出?这是因为 RVO 吗?
案例2
当我打电话时:
MyClass c2 = bar();
cout << c2.id << endl;
输出是:
[222] MyClass::ctor
[222] MyClass::dtor
[4197488] MyClass::ctor&
4197488
[4197488] MyClass::dtor
这里发生了什么?我创建变量然后返回它并且变量被销毁,因为它是范围的结尾。编译器正在尝试通过复制构造函数复制该变量,但它已经被破坏了,这就是为什么我有随机值?那么实际上c2
主要是什么?
案例3
当我打电话时:
MyClass* c3 = baz();
cout << c3->id << endl;
输出是:
[333] MyClass::ctor
333
这是最简单的情况?我返回一个位于堆上的动态创建的指针,因此内存被分配而不是自动释放。当没有调用析构函数并且我有内存泄漏时,就是这种情况。我对吗?
是否还有其他不明显的情况或事情,我应该知道完全掌握 C++ 中的返回值?;) 从函数返回对象的推荐方法是什么(如果有的话) - 有什么经验法则吗?