【问题标题】:Returning a vector, is RVO or a move constructor being applied here?返回一个向量,这里应用的是 RVO 还是移动构造函数?
【发布时间】:2014-07-14 02:31:50
【问题描述】:

我有一个类,它有一个 std::vector 数据成员。然后我有一个简单的 get 成员函数,它只是按值返回数据成员。

class X{
    public:
    vector<shared_ptr<MyClass>> z;

    vector<shared_ptr<MyClass>> X::getVector(){
        return z;
    }
};

当我调用以下 C++ 时:

std::vector<boost::shared_ptr<MyClass>> my_vec = obj->getVector();

这个 x86 是生产出来的:

std::vector<boost::shared_ptr<MyClass>> my_vec = obj->getVector();
mov         rdx,qword ptr [r8+20h]  
test        rdx,rdx  
je          boost::boost::+3DCh (013F0F690Ch)  
lea         rcx,[x]  
call        std::vector<boost::shared_ptr<MyClass>, std::allocator<boost::shared_ptr<MyClass> > >::vector (013F0E9700h)  

我期望应用返回值优化 (RVO) 或 std::vector 移动构造函数。但是,我无法从 x86 中推断出哪个?

【问题讨论】:

  • 您在声明中使用返回值,因此应用了复制构造。我假设你没有使用 C++11,所以没有移动构造

标签: c++ vector move move-semantics rvo


【解决方案1】:

不,成员永远不会自动移动。这会意外地使this 失效。

成员z 被复制到一个临时位置,然后移动或应用RVO。由于您只看到一个构造函数调用,因此它看起来像 RVO。

【讨论】:

  • x86 会显示这些吗?我有兴趣了解将来如何识别这一点。
  • 好吧,我提到只有一个构造函数调用(或根本没有函数调用),并且由于在构造函数调用中必须反映副本,因此似乎存在 RVO。但是,我们通常不会像这样读取可执行代码;使用调试器单步执行它更容易、更可靠。特别是,看起来该函数已被内联,并且周围有一个空检查。
【解决方案2】:

从 cfront 开始,RVO 确实是一个非常基本且古老的编译器优化。如果可能,编译器将尝试在适当的位置构造对象,并摆脱任何复制/移动。 在您的情况下,它与:

std::vector<boost::shared_ptr<MyClass>> my_vec(obj->z);

如果您想确保没有调用额外的复制/移动,只需从 getVector() 中重新获取引用即可;

【讨论】:

  • 抱歉,我认为您误读了我的问题。从我提供的 x86 来看,究竟发生了什么?所以你提到了 RVO,你能在 x86 中看到 RVO 吗?
猜你喜欢
  • 2012-11-13
  • 2015-06-15
  • 2019-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-29
  • 2012-06-02
  • 1970-01-01
相关资源
最近更新 更多