在周末期间,我正在尝试刷新我的c ++技能并学习一些c ++ 11,我偶然发现了以下问题:我无法强制我的容器类正确使用移动构造函数:
我有一个构建器类,其定义如下:
class builder
{
...
container build() const
{
std::vector<items> items;
//... fill up the vector
return container(items); //should move the vector right? wrong!
//return container(std::move(items)); also doesn't work
}
}
类item和容器,定义如下:
class container
{
public:
container(std:vector<item> items)
: items_(items) // always invokes copy constructor on vector, never move
{ }
container(container&& rhs)
{
...
}
...
private:
std::vector<item> items_;
}
class item
{
public:
//move .ctor
item(item && rhs);
item& operator=(item && rhs);
//copy .ctor
item(const item& rhs); //this gets called instead of move .ctor
item& operator=(const item& rhs);
...
}
现在我的代码只使用
builder my_builder;
...
auto result = my_builder.build();
导致首先构建每个项目然后复制...
我应该怎么写以下classess来不复制项目?我应该回去使用标准指针吗?
答案 0 :(得分:22)
您的代码应更改为:
container(std:vector<item2> items) // may copy OR move
: items_(std::move(items)) // always moves
{}
一般情况下:如果你想要自己的东西副本,那么在该参数列表上制作该副本并将其移动到需要的位置。让调用者决定是否要复制或移动现有数据。 (换句话说,你就在那里。现在只需移动你的数据。)
另外:return container(std::move(items));
。之前我没有提到过,因为我错误地认为所有局部变量都是在return语句中自动移动的,但只有返回的值是。 (所以这实际上应该有效:return items;
,因为container
的构造函数不是explicit
。)
答案 1 :(得分:5)
为您写了这个模板启用移动课程。研究它,你就可以得到它。
/// <summary>Container.</summary>
class Container {
private:
// Here be data!
std::vector<unsigned char> _Bytes;
public:
/// <summary>Default constructor.</summary>
Container(){
}
/// <summary>Copy constructor.</summary>
Container(const Container& Copy){
*this = Copy;
}
/// <summary>Copy assignment</summary>
Container& operator = (const Container& Copy){
// Avoid self assignment
if(&Copy == this){
return *this;
}
// Get copying
_Bytes = Copy._Bytes; // Copies _Bytes
return *this;
}
/// <summary>Move constructor</summary>
Container(Container&& Move){
// You must do this to pass to move assignment
*this = std::move(Move); // <- Important
}
/// <summary>Move assignment</summary>
Container& operator = (Container&& Move){
// Avoid self assignment
if(&Move == this){
return *this;
}
// Get moving
std::swap(_Bytes, Move._Bytes); // Moves _Bytes
return *this;
}
}; // class Container
我总是反对使用像这样的值参数:
function(std:vector<item2> items)
我总是使用:
function(const std:vector<item2>& items)
function(std:vector<item2>& items)
function(std:vector<item2>&& items)
特别是对于较大的数据容器,很少:
function(std:vector<item2> items)
对于较小的数据,从不向量。
通过这种方式,您可以控制所发生的事情,这就是为什么我们使用C ++来控制一切。
显然,这一切都取决于你在做什么。
我是一名自学成才的C ++开发人员。远非专家,尤其是C ++俚语......但学习:)