复制构造函数 return 临时对象

Copy constructor return temporary object

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

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

声明说:

If we call myFunction, then C++ will create a new myClass object that's initialized to mc when myFunction returns. Thus while your code might act like it's transparently moving the object from inside of myFunction to the rest of your code, it's actually making a temporary copy.

我认为声明MyClass mc;将创建对象并返回表单函数而不是任何临时对象。 我哪里错了?谁能详细说说容易理解的?

I think statement MyClass mc; will create the object

正确。

and it returned form function not any temporary object.

我不完全理解你的说法,所以我无法判断你是否有误,但事实是这样的:

mc 是局部变量。局部变量在函数退出时被销毁。在它被销毁之前,一个临时对象是从它复制初始化的。然后从函数中 return 编辑临时对象。

额外知识 1:自 C++11 起,如果可能,临时文件由 move 复制初始化。

额外知识 2:标准明确允许编译器跳过 copy/move,而是在调用站点构造对象。这种优化被称为 (named) return 值优化 并且是复制省略的一种形式。尽管如此,您不能 return 既不可复制也不可移动的对象。那是因为执行 NRVO 不需要 C++ 的实现。

假设您有以下代码:

#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 returns 对象 mc 就像你说的。但是你也知道 mc 的析构函数将在 mc 超出范围时被调用 - mc 是在 myFunction 内部声明的,因此析构函数将在函数之后被调用被执行并释放内存(delete[] v)。内存已释放,但值仍在内存中!所以,即使 x=myFunction(); 可以工作,你也会有一个对象,其中 v 指向的内存被释放了!所以,cout<<x.v[2]<<'\n'; 可能 打印不正确。如果你编译代码,它会 可能 打印正确的值 (2),因为内存没有被覆盖,但如果你在 cout 语句之前或一段时间后进行更多分配使用 OS,您会看到打印的值为 incorrect/crash,因为内存将被其他程序覆盖。 v 仍然指向该内存块,但它不知道那里有什么,因为内存已被释放。

内部 myFunction:v -> |0|1| 2 |3|4|...

退出后myFunction:v -> |0|1| 2 |3|4|.....

一些内存分配后:v -> |a|1| b |@|%|3|7|2|1|*|!|......