首页 > 解决方案 > 如何调用移动构造函数?

问题描述

我有以下代码:

#include<iostream>
using namespace std;
class A{
    int size;
    double *arr;

public:
    A(int len):size(len)
    {
        cout<<"ctor called"<<endl;
        arr=new double[size];
    }
    A(const A &rhs)
    {
        cout<<"calling copy ctor"<<endl;
        size=rhs.size;
        arr=new double[size];
    }
    A(A&& rhs)
    {
      cout<<"caling move constructor"<<endl;
      size=rhs.size;
      arr=rhs.arr;
      rhs.arr=nullptr;
    }
    ~A()
    {
        cout<<"Calling Dtor"<<endl;
        delete[] arr;
        size=0;
        arr=NULL;
    }
};
A createVector()
{
    cout<<"Creating object"<<endl;
    A a(20);
    cout<<"returning after creating object a"<<endl;
    return (a);
}
void foo(A v)
{
    cout<<"Class A object rcvd"<<endl;
    return;
}
int main()
{
    //cout<<"a has been rcvd"<<endl;
    foo(createVector());
    return 0;
}

我已经传递了一个“A”类型的临时对象(它已由另一个函数返回)。我期待调用 Move 构造函数。但我得到以下输出:

Creating object
ctor called
returning after creating object a
Class A object rcvd
Calling Dtor

为什么没有调用移动构造函数?此外,如果更改代码如下:

foo(createVector())----->foo(move(createVector()));

我得到以下输出:

Creating object
ctor called
returning after creating object a
caling move constructor
Class A object rcvd
Calling Dtor
Calling Dtor

为什么要调用 Destructor 两次?

标签: c++c++11

解决方案


为什么没有调用移动构造函数?

没有调用移动构造函数,因为移动已经被优化掉了。创建对象时,createVectorA不会在通常用于局部变量的位置创建对象。相反,该对象是在返回值的通常位置创建的。这个返回值被送到main为它指定的地方,即它的“'A'类型的临时对象”。由于这个临时值是按值传递给另一个函数的,所以它是在这些参数的通常位置构造的。

因此,当createVector创建其A名为 的对象时a, 的位置a已经是传递main给的正确位置foo,不需要移动(除非您明确请求移动)。麾!你的编译器效率很高!忽略它并继续关注更重要的问题。(如果这不仅仅是试图理解移动语义,那么您可能正在编写糟糕的代码。)

为什么要调用 Destructor 两次?

因为你强迫两个物体存在。在这种情况下,由返回的临时对象createVector被强制到与用作参数的对象不同的位置foo。两者都需要销毁。(从一个对象移动可能会使该对象处于不可用状态,但它仍然是一个需要销毁的对象。不可用状态确实需要足够连贯,以便析构函数处理。)


推荐阅读