【问题标题】:Passing a container of unique_ptr to constructor?将 unique_ptr 的容器传递给构造函数?
【发布时间】:2015-01-28 22:02:37
【问题描述】:

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

【问题讨论】:

  • 从您的问题中不清楚您遇到了什么问题;如果代码无法编译,则发布编译器错误消息

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


【解决方案1】:

以下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?

【讨论】:

    【解决方案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,并且在main()中构造bar时还添加了显式move

    事实上,你在main()中有这段代码:

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

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

    相反,如果您想触发向量参数的移动,则必须在 vec1 参数上显式调用 std::move()

    【讨论】:

      【解决方案3】:

      这个构造函数(带或不带 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 通过非常量引用获取向量来避免这个问题。但是,如果该构造函数将元素从其参数中移出,这将导致不直观的行为,因此您拥有它的方式可能是最好的。


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

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

      它失败了,因为您无法移出const 向量。要解决这个问题,请去掉 const 这个词,它无论如何都没有用。 (问题的第一部分不受参数是否为const的影响)。

      【讨论】:

        猜你喜欢
        • 2013-02-14
        • 2017-01-02
        • 2012-03-30
        • 2017-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-07
        相关资源
        最近更新 更多