转换为右值引用可防止复制省略

Cast to rvalue reference prevents copy elision

提问人:pauk 提问时间:10/29/2023 更新时间:10/29/2023 访问量:64

问:

我阅读了更多相关文章,但没有一个答案能澄清我的疑问。为什么在下面的代码中,只有在没有强制转换为右值引用时才会进行优化,否则将调用移动(是否提供)或复制(如果没有提供移动构造函数)构造函数。

struct Clasa{
    Clasa(){
        std::cout << "Default" << std::endl;
    }
    Clasa(const Clasa& clasa){
        std::cout << "Copy" << std::endl;
    }
    Clasa(Clasa&& clasa){
        std::cout << "Move" << std::endl;
    }
    ~Clasa(){
        std::cout << "Destructor" << std::endl;
    }
};

int main(){
    Clasa c = (Clasa&&)Clasa();//no optimization
    Clasa d = Clasa();//move/copy elision
} 
C++ 右值引用 移动构造函数 省略

评论

0赞 NathanOliver 10/29/2023
(Clasa&&)Clasa();表示具体化临时并绑定对它的引用。这明确地阻止了省略。
0赞 user12002570 10/29/2023
请注意,从 C++17 开始,是强制性的复制省略。Clasa d = Clasa();
0赞 pauk 10/29/2023
@NathanOliver 感谢您的回复。因此,(Clasa&&) 将 prvalue 转换为 xvalue?另外,std::move(Clasa()) 等同于 (Clasa&&)?
0赞 user17732522 10/29/2023
@pauk 两者都是。这就是为什么调用 prvalue 几乎总是错误的。它应该只在左值上调用。(但是,与 .std::move(Clasa&&)std::move

答:

4赞 user12002570 10/29/2023 #1

在第一种情况下,临时具体化发生,因为您显式绑定了对 prvalue() 的引用,因此此处没有省略。这可以从临时物化中看出:Clasa c = (Clasa&&)Clasa();Class()

在以下情况下会发生临时物化:

  • 将引用绑定到 PREnate 时;

现在来看第二种情况。Clasa d = Clasa();

C++17 及更高版本

从 C++17 开始,有强制性的复制省略。这意味着标准要求将对象直接构造到存储中,否则它将被复制/移动到该存储中。这实质上意味着此处不会观察到任何复制/移动调用。

C++ 之前的版本17

但在 C++17 之前,这可能会导致创建复制初始化的临时使用。这里更详细地解释了这一点。d