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
函数打开了许多大门。