2017-06-30 20 views
-1

的函数返回的对象我有一个小程序,其中我有一个全局函数重载operator +从在C++

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

关于你的代码。如果你有一个像下面

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毕竟符合标准的编译器是使得从所述foo()函数返回的原始Box变量被直接放置在那里它应该在被调用者的堆栈,所以foo()的返回对象是从main()开始的堆栈(假设从main()被调用)此过程被称为elision

+0

感谢您的帮助好奇,正如您所看到的,我还为我的班级“Box”声明了一个复制构造函数,并在构造函数中打印了一些内容。但是当我运行该程序时,由于没有打印任何内容,因此不会调用复制构造函数。这也是优化的结果吗? – vesontio

+0

是的!尝试使用-fno-elide构造函数进行编译。在C++ 17中,这将不会有所作为 – Curious

+1

是的!我试过了'-fno-elide-constructors'选项,现在程序确实调用了copy-constructor。再次感谢你! – vesontio

2

会发生什么情况基本上是 Box对象被创建:一个在main功能,一个在operator+功能。 operator+函数中的Box对象是复制到main函数中的对象中。然后,operator+函数中的对象被销毁,留下的对象位于main函数中。

现代优化编译器做跳过一些上面提到的步骤,最显着的这只会造成一个对象作为其return value optimizations(只创建一个对象的一部分,而不是复制任何东西被称为copy elision,一个学期你在用C++编程时迟早会联系上)。

+0

感谢您的帮助。 – vesontio