5

如果我理解正确,移动语义允许从临时的、未命名的对象中移动和重用资源。RVO,尽管前面的移动语义走得更远,“窃取”了整个对象,以避免额外的构造函数调用和赋值/复制函数。

这对我来说似乎有点反直觉,如果被调用的构造函数直接使用最终左值目标的地址来直接将数据放置在用户需要的地方,那不是更快、更简单和用户明显吗?

我的意思是,“在这个位置创建这个对象”似乎比“在某个地方创建这个对象,然后将它复制到正确的位置”更直观一些。

4

1 回答 1

7

是的,它“有点反直觉”。启用复制省略后,构造函数的所有副作用也会被省略。

#include <iostream>

struct X {
    X() { std::cout << "Construct" << std::endl; }
    X(X&&) { std::cout << "Move" << std::endl; }
    ~X() { std::cout << "Destruct" << std::endl; };
};

X f() { return X(); }

int main()
{
    X x(f());
    return 0;
}

复制省略:g++ -std=c++11 src-test/main.cc

Construct
Destruct

没有复制省略:g++ -std=c++11 -fno-elide-constructors src-test/main.cc

Construct
Move
Destruct
Move
Destruct
Destruct

编译器知道程序/库所针对的硬件,能够应用(可选)复制省略。C++ 语言本身不知道硬件特定的返回机制。因此,在这种情况下,不可能在某个地址进行构造。

于 2013-12-17T12:43:52.163 回答