C ++允许从类成员中移出数据的最佳方法是什么(std :: move语法)

时间:2016-03-04 14:23:49

标签: c++11 move-semantics

想象一下,我有一个类,其主要职责是填充数据容器。我想将数据移出这个类。所以我有:

class cCreator
{  
public: 
   void generate()
   {
      ///generate the content of data_ and populate it
      ....
      ....
   }

   //variation 1
   std::vector<int>&& getData1()
   {
      return std::move(data_);
   }

   //variation 2
   std::vector<int> getData2()
   {
      return std::move(data_);    
   }
private:
      std::vector<int> data_
};

getData()的变体1和变体2之间的区别是什么。当我省略&amp;&amp;和从函数定义??

3 个答案:

答案 0 :(得分:3)

在第一种情况下,函数本身实际上没有移动。您只是返回一个右值引用,它允许原始调用者在需要时移动。在第二种情况下,无论调用者如何使用结果,数据实际上都会被移动到临时数据中。

cCreator c1, c2;
c1.getData1(); // no move
std::vector<int> v1 = c1.getData1(); // move directly from data_
                                     // into v1.
c2.getData2(); // move to temporary, which isn't used.
std::vector<int> v2 = c2.getData1(); // move from data_ to temporary,
                                     // then move from temporary to v2.

答案 1 :(得分:1)

版本1可能是一个坏主意,f(x.getData())之类的内容可能会移动或不移动,具体取决于f的签名。一般来说,我们希望任何move在代码中都是明确的,所以你至少应该有类似的东西:

std::vector<int>&& getData() &&
{
  return std::move(data_);
}

所以现在移动必须是明确的:f( std::move(x).getData() ),你可能想为观察提供const &的重载。

如果它有另一个名字,那么版本2就没问题了。根据我的经验,99%的人认为getX是非修改操作。最好称之为releaseData,这与unique_ptr::release的命名一致。

答案 2 :(得分:1)

我想在这种特定情况下,其数据被提取(移动)的容器是一个stl向量,std :: swap将是一个有效的选项。所以简单地提供:

const std::vector<int>& getData() const;
std::vector<int>& getData();

woudl使用户能够安全地提取数据,如果他愿意的话。如果由于某种原因C ++ 11不可用,这可能只是可行的选择。