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

5
我在这里错过了什么?为什么我不能将向量作为类构造函数的一部分移动?从构造函数中删除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;
}

1
从你的问题中并不清楚你遇到了什么问题;如果代码无法编译,则请发布编译器错误消息。 - M.M
3个回答

5
以下代码应该可以正常编译:链接
#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;
}

我已经将您的其余代码保持不变,但是您可能需要阅读为什么“using namespace std;”被认为是不良实践?


4
这段代码对我来说运行良好:
#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”,并且在构造“bar”时在“main()”中添加了显式的“move”。
事实上,在“main()”中有以下代码:
vector<unique_ptr<char>> vec1 (move(vec)); //ok
Bar bar(vec1);
但是这段代码在构建bar时需要一个副本vec1向量。由于vec1被定义为unique_ptrvector,而unique_ptr可移动但不可复制,编译器发生错误:无法复制vec1向量。
相反,如果要触发向量参数的移动,必须明确调用std::move()来移动vec1参数。

2

这个构造函数(带或不带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

如果Bar::Bar使用非const引用来传递向量,则可以避免此问题。但是,如果该构造函数将元素移出其参数,则会导致不直观的行为,因此现在的方式可能是最好的。


问题的第二部分是在您实际成功调用Bar::Bar后,它要执行什么操作。在这个版本中:

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

出现错误是因为您无法移动一个const向量。要解决此问题,请删除无用的const单词。无论参数是否为const,问题的第一部分都不受影响。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接