在return语句中调用构造函数

hac*_*ock 4 c++ visual-c++

class test{

public:

    int data;
    test(const test& ){cout<<"INSIDE COPY CON "<<endl;}
    test(int val = 0) : data(val){ cout<<"INSIDE CON "<<endl; }

    test testfun(const test& obj)
    {
        cout<<"data : "<<data<<endl;
        //test test3(this->data + obj.data);
        //cout<<"test3 :"<<test3.data<<endl;
        //return test3;   //This will work only if return type is changed to const ref
        return test(data + obj.data); 


    }
};

int main()
{

    test testO1(1);
    test testO2(2);
    test testO3 = testO1.testfun(testO2);

    cout<<testO3.data<<endl;


    getchar();


}
Run Code Online (Sandbox Code Playgroud)

OUTPUT:

INSIDE CON

INSIDE CON

data : 1

INSIDE CON

3
Run Code Online (Sandbox Code Playgroud)

在return语句中调用构造函数时会发生什么?因为我能够按价值返回并且它起作用我认为它不是临时位置.或者它是将对象创建为临时的并使用复制构造函数来复制值,这就是为什么复制构造函数中的打印没有被打印的情况.

Jon*_*ely 10

它会创建一个临时对象,然后将其复制到返回值.

但是为了提高效率,C++允许省略对复制构造函数(或C++ 11中的移动构造函数)的调用,因此您不应该依赖复制构造函数的副作用.

请参阅返回值优化想要速度?通过价值

  • @rocky:RVO意味着对象本质上不是复制,而是在被调用变量的内存空间中构造(在你的情况下为`testO3`).为什么你需要*来调用复制构造函数? (2认同)

thb*_*thb 7

你问了一个尖锐的问题。

由编译器和相关的工具链来决定做什么,但基本模式如下。在调用之前testfun(),调用者 [ main(),在您的示例中] 为test03堆栈保留空间。然后它传递test03to的地址testfun()

该函数testfun()必须以某种方式将一个test对象放在调用者提供的地址上。如果函数只有一个 return 语句,则可以自由使用调用者提供的存储来构建返回值。它不需要使用自己的存储。它可以使用main()的。

现在,这种策略并不总是奏效。当一个函数testfun()有两个不同的返回语句时,它通常会失败,其中一个或两个返回的不是临时对象而是一个命名对象。在这种情况下,编译器将被迫执行其他不必要的复制返回。但是,更常见的情况与您的情况类似,即testfun()直接在需要的位置构建返回值main()。在这种情况下,不会发生实际的复制。

因此,由编译器决定在这种情况下是否在返回时调用复制构造函数。