-2

可能重复:
没有调用复制构造函数

在此代码中,从不调用复制构造函数(也不调用移动构造函数或赋值运算符)。怎么可能?有人可以解释函数如何返回值,堆栈和寄存器会发生什么(或发布一些好的链接)吗?

    #include <iostream>
#include <cstring>

using namespace std;

class Test;

Test getnew(int arg);
class Test
{

  public:
    char *conts;
    int len;
        Test(char* input = NULL){conts = new char[len=10];
            if(input)strncpy(conts,input,9);else strcpy(conts,"xxxxx");
            cout << "\nconstructor: " << conts;
        };
        Test(const Test& t){
                conts = new char[10];
                if(t.len)strncpy(conts,t.conts,9);
                len = t.len;
                cout << "\ncopy-constructor: " << conts;
        };
        Test(Test&& t){
               conts = t.conts;
               t.conts = NULL;
               std::swap(len,t.len);
               cout << "\nmove-constructor: " << conts;
        };

        ~Test(){
            cout << "\ndestructor";
            if(conts)delete [] conts;
             len = 0;
             conts = NULL;
        };
        Test& operator=(Test rhs)
        {
            std::swap(conts,rhs.conts);
            std::swap(len,rhs.len);
            cout << "\nassigend: " << conts;
        }

};

int main()
{

   Test t2 = getnew(1);
   cout << endl << t2.conts;
    return 0;
}

Test getnew(int arg)
{
        Test retj("FFFFF");
        return retj;
}

只调用了一个构造函数和一个析构函数。但是对象 t2 具有使用正确值“FFFF”初始化的值成员 conts。我知道应用了返回值优化,但是对象 t2 是如何初始化的?

4

2 回答 2

4

理论上,应该发生的是编译器会创建一个返回值的临时副本,然后将该临时对象分配给接收函数输出的变量。

但是,即使复制构造函数或移动构造函数有副作用,编译器也可以省略返回值的复制和移动。在您的情况下,这变成了所谓的NRVO (命名返回值优化),这是RVO(返回值优化)的一个特例。

因此,您所看到的很可能是移动省略的结果。有一些编译器选项可以禁用此优化,但一些编译器(例如 Clang 3.2)在处理这些选项时存在错误(请参阅此问题的答案)。

于 2013-01-20T16:53:34.137 回答
0

使用返回值优化T2赋值给Test初始化的对象getnew。这就是 RVO 的工作原理。

于 2013-01-20T16:49:23.343 回答