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


#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)时使用移动构造函数。

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

您的send函数返回b是一个参数,而不是本地变量:

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

因此,没有发生RVO优化,因为返回参数会禁用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然后跳进去。

它正在移动从参数b构造返回值,然后将返回值移动到b1

最新更新