【问题标题】:move semantics behaviour on vector return向量返回时移动语义行为
【发布时间】:2012-11-04 20:43:46
【问题描述】:

我一直在玩 c++11 移动语义

在代码中...

#include <vector>
#include <string>

std::vector<std::string> GetNewVector()
{
  std::vector<std::string> newVec; 
  newVec.push_back(std::string("hello")); //(1)
  newVec.push_back(std::string("whey")); //(2)

  return newVec;
}

int main(int argc, char* argv[])
{
  std::vector<std::string> vec = GetNewVector();
}

在点 (1) 处,“hello”对象的移动构造函数在对象移动到向量中时被调用。

在第 (2) 点,首先再次调用“hello”的移动构造函数(我假设这是向量重新分配的位置),然后调用“乳清”移动构造函数。

这一切都符合预期,但是我希望在GetNewVector() 末尾返回向量时再次移动对象,但是不会再次调用移动构造函数。我的猜测是 RVO 正在发生,但是当我在调试模式下运行 Visual Studio (2k10) 时,我不确定这是否会发生?

如果可以执行RVO,那么它是否会优先于使用移动构造函数?

【问题讨论】:

  • 这是什么语言? TString (CERN ROOT?) std::vector 没有指定类型?
  • 你所拥有的是逻辑上的副本,而不是移动。要采取行动,您必须执行return std::move(newVec)
  • @VaughnCato:糟糕糟糕糟糕!在此处使用std::move 会禁止RVO,并且标准已经规定编译器首先必须尝试移动newVec,并且只有在移动失败时才复制它。
  • @Xeo:我并不是要暗示你想要那样做。
  • @VaughnCato:我在评论中试图解释的是,如果未应用 NRVO,return a_local_variable; 将已经执行移动。

标签: c++ c++11 move-semantics


【解决方案1】:

如果指定容器移动是按元素移动的,那么移动容器的优势将被严重削弱。

取而代之的是,他们只是简单地采用其他内部胆量,即在std::vectors 情况下指向动态分配数组的指针,这将元素留在它们所在的位置,这使得这是一个恒定的复杂性操作。如果您进行元素级移动,您将看到线性复杂性操作。

如果可以执行RVO,那么它是否会优先于使用移动构造函数?

该标准在这方面有点限制,但是是的,RVO(通常是复制省略,也涵盖与其名称相反的移动)当然会优先于其他任何东西,因为它更快。 :)

请注意,自动移动仅在复制省略可以可以完成的情况下完成,但不是出于任何原因。有关自动移动的更复杂细节,另请参阅 this question

【讨论】:

  • 啊好吧,那么指向向量内部原始数组的指针只是简单地复制了?有道理,谢谢
  • @TomP89:嗯,复制了,然后旧指针设置为空,所以当旧向量超出范围时,它不会尝试删除数组。 :)
猜你喜欢
  • 2016-11-11
  • 2021-07-24
  • 2013-10-08
  • 2014-03-11
  • 1970-01-01
  • 2019-08-16
相关资源
最近更新 更多