复制构造函数返回临时对象

时间:2016-06-09 14:39:49

标签: c++ copy-constructor

我正在准备关于复制构造函数的讲座,并发现了这个:

MyClass myFunction()
{
   MyClass mc;
   return mc;
}
声明说:

  

如果我们调用myFunction,那么C ++将创建一个新的myClass对象   当myFunction返回时,它被初始化为mc。这样你的代码   可能会像透明地从内部移动物体一样   myFunction到你的其余代码,它实际上是临时的   副本。

我认为声明MyClass mc;将创建对象并返回表单函数而不是任何临时对象。 我哪里错了?有人可以说明这个陈述能够轻易理解吗?

2 个答案:

答案 0 :(得分:3)

  

我认为声明MyClass mc;将创建对象

正确。

  

它返回表单函数而不是任何临时对象。

我不完全理解你的陈述,所以我不知道你是否出错,但这就是:

mc是一个局部变量。函数退出时会破坏局部变量。在销毁之前,会从中复制初始化临时对象。然后从函数返回临时对象。

额外知识1:从C ++ 11开始,如果可能,临时由 move 进行复制初始化。

额外知识2:标准明确允许编译器跳过复制/移动,而是在调用站点构造对象。此优化称为(命名)返回值优化,是一种复制省略。尽管如此,您仍然无法返回既不可复制也不可移动的对象。这是因为不需要使用C ++实现NRVO。

答案 1 :(得分:1)

假设你有这段代码:

#include <iostream>
using namespace std;

class MyClass
{
public:

    int *v;

    MyClass()
    {
        v=new int[5];
        for(int i=0;i<5;i++) v[i]=i;  // x will look like : 0,1,2,3,4
    }

    ~MyClass()
    {
        cout<<"Destructor called! Now v is deallocated! \n";
        delete[] v;
    }
};

MyClass myFunction()
{
   MyClass mc;
   return mc;
}

int main()
{
    MyClass x;

    x=myFunction();

    cout<<x.v[2]<<'\n'; //it may or may not print the right thing

    return 0;
}

如您所见,myFunction像您所说的那样返回对象mc。但是你也知道mc的析构函数将在mc超出范围时被调用 - mcmyFunction内被声明,因此析构函数将在函数后被调用执行并释放内存(delete[] v)。内存被释放,但值仍然存在于内存中!所以,即使x=myFunction();可行,你也会有一个内存v指向的对象被释放!因此,cout<<x.v[2]<<'\n'; 可能无法打印正确的内容。如果你编译代码,可能打印正确的值(2),因为内存没有被覆盖,但如果你在cout语句之前或者在使用你的一段时间后再做一些分配操作系统,您将看到打印的值不正确/崩溃,因为内存将被其他程序覆盖。 v仍然指向那个内存块,但它不知道那里有什么,因为内存被释放了。

内部myFunction:v - &gt; |0|1| 2 |3|4|...

退出myFunction后:v - &gt; |0|1| 2 |3|4|.....

经过一些内存分配后:v - &gt; |a|1| b |@|%|3|7|2|1|*|!|......