Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++11 C++;允许将数据移出类成员的最佳方式是什么(std::move语法)_C++11_Move Semantics - Fatal编程技术网

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

C++11 C++;允许将数据移出类成员的最佳方式是什么(std::move语法),c++11,move-semantics,C++11,Move Semantics,假设我有一个类,其主要职责是填充数据容器。我想把数据移出这个类。因此,我: class cCreator { public: void generate() { ///generate the content of data_ and populate it .... .... } //variation 1 std::vector<int>&& getData1() { re

假设我有一个类,其主要职责是填充数据容器。我想把数据移出这个类。因此,我:

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_
};
类创建器
{  
公众:
void生成()
{
///生成数据内容并填充它
....
....
}
//变体1
std::vector&&getData1()
{
返回标准::移动(数据);
}
//变化2
std::vector getData2()
{
返回标准::移动(数据);
}
私人:
矢量数据_
};

S getData()的变体1和变体2之间的区别是什么。当我从函数定义中省略&时会发生什么变化?

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

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.
cCreator c1、c2;
c1.getData1();//不许动
std::vector v1=c1.getData1();//直接从数据移动_
//进入v1。
c2.getData2();//移动到临时位置,该位置不使用。
std::vector v2=c2.getData1();//从数据移动到临时,
//然后从临时移动到v2。

版本1可能是个坏主意,像
f(x.getData())
这样的东西可能正在移动或不移动,这取决于
f
的签名。一般来说,我们希望任何
move
在代码中都是显式的,因此您至少应该有如下内容:

std::vector<int>&& getData() &&
{
  return std::move(data_);
}
std::vector&&getData()&&
{
返回标准::移动(数据);
}
因此,现在移动必须是显式的:
f(std::move(x).getData())
,您可能希望为
const&
提供一个重载,仅用于观察


如果版本2有另一个名称,它就可以了。根据我的经验,99%的人认为
getX
是一种非修改操作。最好将其命名为
releaseData
,这与
unique\u ptr::release

的命名一致。我想在这种特定情况下,提取(移动)数据的容器是stl向量,std::swap将是一个有效的选项。因此,只需提供:

const std::vector<int>& getData() const;
std::vector<int>& getData();
常量std::vector&getData()常量; std::vector&getData();
如果用户愿意,将允许用户安全地提取数据。如果C++11因某种原因不可用,这可能是唯一可行的选项。

旁边有一点注释:注意,由于对
getData()
的调用会破坏成员,您可能需要向函数添加右值引用限定符:
std::vector cCreator::extractData()&&
。这样,您就可以强制调用方提供一个用于提取数据的右值引用,这使得从对象中删除成员的操作更加明确。也就是说,
obj.extractData()
将不再编译,但
std::move(obj).extractData()
将不再编译。如果完成RVO,则最后一种情况不一定意味着临时操作,但行为将是您描述的针对getData()命名的+1。其他命名建议:moveData、popData、peekData。我从不使用任何“get”函数,因为其意图总是不明确的。最佳使用data()进行常量访问,其中一个更清晰的操作名称用于修改操作。@galinette我也有相同的意见,然后
get(tuple)
发生了,这为
getX
函数打开了许多大门。