将unique_ptr的容器传递给构造函数?

时间:2014-11-30 22:54:00

标签: c++ constructor containers move unique-ptr

我在这里缺少什么?为什么我不能将矢量作为类构造函数的一部分移动?从构造函数中删除const也没有帮助。

#include <iostream>
#include <vector>
#include <memory>

using namespace std;

class Bar
{
public:
  Bar(const vector<unique_ptr<char>> vec);
  vector<unique_ptr<char>> vec_;
};

Bar::Bar(const vector<unique_ptr<char>> vec) :
  vec_(move(vec)) //not ok
{
}

int main()
{
  vector<unique_ptr<char>> vec;
  vec.push_back(unique_ptr<char>(new char('a')));
  vec.push_back(unique_ptr<char>(new char('b')));
  vec.push_back(unique_ptr<char>(new char('c')));
  vector<unique_ptr<char>> vec1 (move(vec)); //ok
  Bar bar(vec1);
  return 0;
}

3 个答案:

答案 0 :(得分:2)

以下should compile fine

#include <iostream>
#include <vector>
#include <memory>

using namespace std;

class Bar
{
public:
  Bar(vector<unique_ptr<char>> vec);
  vector<unique_ptr<char>> vec_;
};

Bar::Bar(vector<unique_ptr<char>> vec) : // If you intend to move something,
                                         // do not make it const, as moving
                                         // from it will in most cases change
                                         // its state (and therefore cannot be
                                         // const-qualified).
  vec_(move(vec))
{
}

int main()
{
  vector<unique_ptr<char>> vec;
  vec.push_back(unique_ptr<char>(new char('a')));
  vec.push_back(unique_ptr<char>(new char('b')));
  vec.push_back(unique_ptr<char>(new char('c')));
  vector<unique_ptr<char>> vec1 (move(vec));
  Bar bar(std::move(vec1)); // Just like the line immediately above,
                            // the explicit `move` is required, otherwise
                            // you are requesting a copy, which is an error.
  return 0;
}

我保留了其余代码,但您可能需要阅读Why is “using namespace std;” considered bad practice?

答案 1 :(得分:2)

此代码适用于我:

#include <iostream>
#include <memory>
#include <vector>
using namespace std;

struct Bar
{
    Bar(vector<unique_ptr<char>> vec)
        : Vec(move(vec))
    { }

    vector<unique_ptr<char>> Vec;
};

int main()
{
    vector<unique_ptr<char>> vec;
    vec.push_back(unique_ptr<char>(new char('a')));
    vec.push_back(unique_ptr<char>(new char('b')));
    vec.push_back(unique_ptr<char>(new char('c')));

    vector<unique_ptr<char>> vec1(move(vec));

    Bar bar(move(vec1));
}

请注意,我删除了构造函数参数中的const,并在move中构建bar时添加了显式main()

事实上,您在main()中使用了此代码:

vector<unique_ptr<char>> vec1 (move(vec)); //ok
Bar bar(vec1);

但是,在构建vec1时,该代码需要bar向量的副本。由于vec1被定义为vector unique_ptr,并且由于unique_ptr可移动但无法复制,因此编译器发出错误:无法复制vec1向量。

相反,如果要触发向量参数的移动,则必须明确调用std::move()参数上的vec1

答案 2 :(得分:1)

此构造函数(带或不带const)接受矢量按值

Bar::Bar(const vector<unique_ptr<char>> vec)

传值意味着通过复制传递的参数构造向量vec。但是,unique_ptr不可复制。因此,只能使用xvalue调用此函数(即,即将被销毁的临时向量,或者通过调用std::move或其他方式明确允许移出的向量)。

所以要调用这个构造函数:

Bar bar( vec1 );               // FAIL: not allowed to take a copy of vec1
Bar bar( std::move(vec1) );    // OK: move pointers out of vec1 in order to create bar

可以通过非{const引用Bar::Bar获取向量来避免此问题。但是,如果构造函数将元素移出其参数,这将导致不直观的行为,因此您拥有它的方式可能是最好的。


问题的第二部分是Bar::Bar在您实际设法调用它之后所做的事情。在这个版本中:

Bar::Bar(const vector<unique_ptr<char>> vec) : vec_(move(vec)) 

它失败了,因为你无法移出const向量。要解决此问题,请取出无用的任何目的const。 (问题的第一部分不受参数是否为const)的影响。