【问题标题】:Why is the move constructor/assignment called when setting an object equal to the return value of another function为什么在设置对象等于另一个函数的返回值时调用移动构造函数/赋值
【发布时间】:2018-02-22 10:05:43
【问题描述】:
#include <iostream>

class Box{
public:
int x;
Box(){
    x=0;
    std::cout << "Constructor" << std::endl;
}
Box(const Box& other){
    x = other.x;
    std::cout << "Copy constructor" << std::endl;
}
Box(Box&& other){
    x = other.x;
    other.x = 0;
    std::cout << "Move constructor" << std::endl;
}

Box& operator=(Box&& other) {
    x = other.x;
    other.x = 0;
    std::cout << "Move assignment" << std::endl;
    return *this;
}

Box& operator=(const Box &other){
    x = other.x;
    std::cout << "Copy assignment" << std::endl;
}

~Box(){
    std::cout << "Destructor" << std::endl;
    x=0;
}
};
Box send(Box b){
std::cout << "Sending" << std::endl;
return b;
}
int main(){
Box b1, b2;
b1 = send(b2);
return 0;
}   

在输出中:

Constructor
Constructor
Copy Constructor
Sending
Move Constructor
Move Assignment
Destructor
Destructor
Destructor
Destructor

我不太清楚为什么在执行b1 = send(b2) 时使用移动构造函数然后赋值。

【问题讨论】:

  • 你必须创建一个临时返回值。
  • 我猜(不要引用我的话)这是因为你在发送函数中创建了一个 Box 的副本,因为它在离开函数范围时被删除,它调用移动赋值,因为返回值可以被视为右值。不过目前无法检查,这只是我的猜测

标签: c++


【解决方案1】:

为什么设置一个对象等于另一个函数的返回值时调用移动构造函数/赋值

您的send 函数返回b,它是一个参数,而不是一个局部变量:

Box send(Box b) {
    std::cout << "Sending" << std::endl;
    return b; // b is a parameter
}

所以没有发生 RVO 优化,因为returning a parameter disables RVO。 同时,还有另一个优化选项可用,隐式std::move

Box send(Box b) {
    std::cout << "Sending" << std::endl;
    return std::move(b); // implicit std::move is applied.
}

所以它是使用你的移动构造函数构造的:

Box(Box&& other);

如果您创建并返回一个局部变量 c,则不会看到移动构造:

Box send(Box b) {
    Box c;
    std::cout << "Sending" << std::endl;
    return c; // Returns c, not b -> No move construction thanks to RVO
}

因为 RVO 然后会跳进去。

【讨论】:

    【解决方案2】:

    它从参数b 移动构造返回值,然后将该返回值移动分配给b1

    【讨论】:

      猜你喜欢
      • 2019-11-16
      • 2015-08-04
      • 2020-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-21
      • 2016-06-25
      相关资源
      最近更新 更多