我有一个小程序,我有一个全局函数重载运算符+
:
class Box {
public:
Box (int, int);
Box (const Box&);
~Box ();
int get_width() const;
int get_length() const;
private:
int width;
int length;
};
Box operator+(const Box& a, const Box& b) {
int w, l;
w = a.get_width() + b.get_width();
l = a.get_length() + b.get_length();
return Box(w, l);
}
在函数operation+
中,我返回了类Box
的对象,因为对象没有通过运算符new
实例化,对象是在栈上分配的,不是吗?
int main (int argc, char *argv[]) {
Box a(100, 200);
Box b(101, 202);
Box c = a + b;
cout << "width: " << c.get_width() << "; length: " << c.get_length() << endl;
return 0;
}
在我的main
函数中,我尝试添加2个框a + b
,并打印框c
的大小。事实证明,对象c
已经持久化,这意味着在执行函数operator+
之后它不会从堆栈中删除。或者,对象c
实际上是在堆中分配的?
我很困惑,有人可以向我解释这个吗?
答案 0 :(得分:2)
基本上会创建两个 Box
个对象:一个在main
函数中,另一个在operator+
函数中。 Box
函数中的operator+
对象 已复制 到main
函数中的对象中。然后,operator+
函数中的对象被破坏,在main
函数中留下对象。
现代优化编译器确实跳过了上面提到的一些步骤,最值得注意的是它只会创建一个单个对象作为其return value optimizations的一部分(只创建一个对象而不是复制任何东西都称为copy elision,这个术语迟早会在用C ++编程时与之联系。)
答案 1 :(得分:0)
关于你的代码。如果您有类似以下的功能
Box foo() {
auto box_one = Box{};
auto box_two = Box{};
return box_one + box_two;
}
int main() {
auto box = foo();
// use box
}
此foo()
函数中的局部变量在函数的堆栈中开始(有关详细信息,请参见下面的最后一段),并将其复制(再次参见下文)到变量box
中,该变量位于堆叠为main()
box
中main()
变量的生命周期与周围范围相关,在本例中为main()
的持续时间。对象在函数main()
的堆栈上分配,它就是它所在的位置。
在大多数优化编译器(前C ++ 17)和C ++ 17之后的所有标准符合编译器中发生的事情是放置从Box
函数返回的原始foo()
变量直接它应该在被调用者的堆栈中,所以foo()
的返回对象从一开始就在main()
堆栈中(假设它从main()
调用)此过程称为elision