通过移动对象用r值引用调用函数接受参数两次是否安全?

时间:2019-05-21 20:58:05

标签: c++

我有以下代码。我以为它会失败,即我以为移动构造函数会在输入“发送”功能时执行,并且当再次尝试调用“发送”时,这应该是无效操作(“ a”不再是有效对象,因为它已被移动从)。但是以某种方式执行该代码不会出现任何问题。 输出显示甚至没有执行move构造函数。

#include <iostream>
using namespace std;

struct A {
    int *ptr;
    A() { cout << "ctor A" << endl; ptr = new int(1); }
    A(A&& o) { cout << "move ctor" << endl; ptr = o.ptr; o.ptr = nullptr; }
    ~A() { cout << "dtor" << endl; delete ptr; }
    void send() { cout << *ptr << endl; }
};

bool send(A&& a, int i)
{
    if (i == 0) { 
        cout << "returning" << endl; 
        return false; 
    }
    cout << "sending" << endl;
    a.send();
    return true;
}
int main()
{ 
    A a;
    if(!send(move(a),0))
        send(move(a),1);
}

输出:

ctor A
returning
sending
1
dtor

但是,当我更改“发送”方法以按值接受A对象时,问题恰好出现了我的想象。调用了Move ctor,并且在第二次调用“ send”时,“ a”无效,因此出现了分段错误。

bool send(A a, int i)
{
    if (i == 0) { 
        cout << "returning" << endl; 
        return false; 
    }
    cout << "sending" << endl;
    a.send();
    return true;
}

结果:

ctor A
move ctor
returning
dtor
move ctor
sending
Segmentation fault

因此,仅当按值传递移动的对象时,才调用move构造函数。好,知道了。

但是我的问题是:这样声明函数“发送”是否安全,即通过r值引用接受参数,然后多次通过移动对象调用它?我知道std :: move不会真正移动任何东西,只会创建r值引用,但是无论如何:它安全吗?或者换句话说,是否有一条指导方针说“不要这样做”?

[https://wandbox.org/permlink/R5spfEGI7WZR9lwR][1]

1 个答案:

答案 0 :(得分:0)

如果实际上在send函数中移动了对象,那么您将看到预期的行为(调用a.send时出现段错误)。例如:

bool send(A &&a, int i)
{
    A b = move(a);

    if (i == 0) { 
        cout << "returning" << endl; 
        return false; 
    }
    cout << "sending" << endl;
    a.send();
    return true;
}