将std :: vector传递给构造函数并移动语义

时间:2012-04-01 10:49:14

标签: c++ c++11

在周末期间,我正在尝试刷新我的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来不复制项目?我应该回去使用标准指针吗?

2 个答案:

答案 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 ++来控制一切。

  • 如果您需要可写副本,只需将const引用自己复制到变量中。
  • 如果您需要只读,则const引用会阻止新副本。
  • 如果您想编辑原文,只需使用参考。
  • 当您感到懒惰时,请使用小数据的值参数。

显然,这一切都取决于你在做什么。

我是一名自学成才的C ++开发人员。远非专家,尤其是C ++俚语......但学习:)