2011-09-27 85 views
2

有这样的代码:对象从功能和拷贝构造函数返回

#include <iostream> 

class A { 
public: 
    int a; 
    A() : a(0) { 
     std::cout << "Default constructor" << " " << this << std::endl; 
    } 
    A(int a_) : a(a_) { 
     std::cout << "Constructor with param " << a_ << " " << this << std::endl; 
    } 
    A(const A& b) { 
     a = b.a; 
     std::cout << "Copy constructor " << b.a << " to " << a << " " << &b << " -> " << this << std::endl; 
    } 
    A& operator=(const A& b) { 
     a=b.a; 
     std::cout << "Assignment operator " << b.a << " to " << a << " " << &b << " -> " << this << std::endl; 
    } 
    ~A() { 
     std::cout << "Destructor for " << a << " " << this << std::endl; 
    } 
    void show(){ 
     std::cout << "This is: " << this << std::endl; 
    } 
}; 


A fun(){ 
    A temp(3); 
    temp.show(); 
    return temp; 
} 


int main() { 
    { 
     A ob = fun(); 
     ob.show(); 
    } 
    return 0; 
} 

结果:

Constructor with param 3 0xbfee79dc 
This is: 0xbfee79dc 
This is: 0xbfee79dc 
Destructor for 3 0xbfee79dc 

目标对象OB是由函数fun()初始化。为什么复制构造函数没有在那里调用?我认为,当函数按值返回时,将调用复制构造函数或赋值运算符。看起来函数fun()中构造的对象在执行函数后不会被销毁。在这种情况下,拷贝构造函数如何被强制调用?

这是由g ++编译的。

回答

4

为什么不在那里调用构造函数?

RVO

如何可以拷贝构造函数被迫在这种情况下调用?

将选项传递给编译器。对于海湾合作委员会,它是--no-elide-constructors选项来禁用RVO

3

这就是所谓的命名返回值优化复制省略,基本上意味着编译器已经想通了,副本可以通过仔细放置临时可以避免和对象在同一个内存位置。

默认情况下,会有在这段代码的三个对象,tempfun,返回值和ob内主,以及多达两个副本,但是通过仔细放置temp在相同的存储单元返回的对象在fun之内并且将ob置于相同的存储器地址中,两个副本可以被优化掉。

我写的关于这两个优化与一对夫妇的照片来解释这到底是怎么回事: