如果 std::move 用作 &&&参数的参数,它是否会调用复制运算符?

Does std::move invoke the copy operator if it's used as an argument on a && parameter?

本文关键字:参数 调用 复制 运算符 是否 move std 用作 如果      更新时间:2023-10-16

这是我的代码:

#include <iostream>

class carl{
    public:
    int x;
    carl(int y):x(y){
    }

    carl(carl&& other)
    {
    std::cout<<" cons called?"<<std::endl;
    this->x = other.x;
    other.x = 0;
    }

    void operator=(carl&& other){
    std::cout<<"operator called?"<<std::endl;
    this->x = other.x;
    other.x = 0;
    }
};

void funct(carl&& get){
std::cout<<get.x<<std::endl;    
}

int main(int argc, char** argv) {
    carl c(2);
    funct(std::move(c));
    std::cout<<c.x<<std::endl;
    return 0;
}

输出:

2
2

如果我还记得的话,有一条针对特殊成员函数的特殊规则规定,如果一个类声明了移动构造函数/运算符,那么该类将不会自动生成复制运算符/构造函数

根据我的示例,移动运算符和构造函数似乎没有被调用,而是复制了值。它本应清空c'x的值,并进行cout来确认,但这些都没有发生。有人能澄清我的代码发生了什么吗?

您的代码中没有发生任何移动。func将引用作为参数,因此传递std::move(c)只是绑定引用——不会发生复制或移动。关键的事实是std::move不会移动,它只是返回一个指定对象的右值。如果您按值计算参数:

void func(carl get);

然后,您将创建一个新对象,该对象使用move构造函数进行初始化(假设您将右值传递给func)。

例如,这里的

void funct(carl&& get) { std::cout<<get.x<<std::endl; }

给出与完全相同的行为

void funct(carl& get) { std::cout<<get.x<<std::endl; }

即:传递对函数的引用。


只有当将右值引用移动到新对象中时,情况才会发生变化:

void funct(carl&& get)
{   
    auto my_carl = std::move(get); 
    std::cout<<my_carl.x<<std::endl;
}

然后编译器调用carl的move构造函数将内容移出对象,而不是进行复制。