【问题标题】:Is it possible to create a std::vector<std::unique_ptr<Bar>> using the fill constructor?是否可以使用填充构造函数创建 std::vector<std::unique_ptr<Bar>> ?
【发布时间】:2016-04-20 17:28:14
【问题描述】:

我有一个类Foo,有一个std::vector&lt;std::unique_ptr&lt;Bar&gt;&gt;类型的成员变量,我想填写这个类的构造函数的初始化列表。这可能吗?

我希望可以使用向量的填充构造函数,像这样

Foo::Foo(int n):
    vector<unique_ptr<Bar>> (n, unique_ptr<Bar> (new Bar))
{}

但我认为这需要std::unique_ptr 的复制构造函数,它被删除(应该是)(unique_ptr(const unique_ptr&amp;) = delete)。

有没有更好的方法来解决这个问题?

【问题讨论】:

  • 你是对的,因为你只调用一次new Bar,所以你的尝试是行不通的,而对于唯一指针的向量,你需要为每个元素调用一次new Bar。我想你最好只使用 emplace_back 的循环。
  • 或者,您可以用空的unique_ptrs 填充构造,然后循环调用每个reset(new Bar)
  • 在 C++ 获得可迭代协程之前,我认为你最好的选择是循环。
  • @zneak 以前从未听说过“可迭代协程”。有解释的链接吗?

标签: c++ c++11 vector stl unique-ptr


【解决方案1】:

既然不可复制,那就移动吧!

使用硬编码对象的解决方案:

#include <memory>
#include <vector>
#include <iterator>
class Bar{};
class Foo{
    public:
    Foo():bars(get_bars()) {}
    std::vector<std::unique_ptr<Bar>> bars;

    private:
    std::vector<std::unique_ptr<Bar>> get_bars(){
        std::unique_ptr<Bar> inilizer_list_temp[]={std::make_unique<Bar>(),std::make_unique<Bar>(),std::make_unique<Bar>()};
        return  std::vector<std::unique_ptr<Bar>>{std::make_move_iterator(std::begin(inilizer_list_temp)),std::make_move_iterator(std::end(inilizer_list_temp))};
    }
};
int main()
{
    Foo foo;
}

Live Demo

对象数量动态的解决方案:

#include <memory>
#include <vector>
#include <iterator>
#include <iostream>
class Bar{
    public:
    int a=5;
    };
class Foo{
    public:
    Foo():bars(get_bars(10)) {}
    std::vector<std::unique_ptr<Bar>> bars;

    private:
    std::vector<std::unique_ptr<Bar>> get_bars(int n){
        std::vector<std::unique_ptr<Bar>> inilizer_list_temp;
        inilizer_list_temp.reserve(n);
        for(size_t i=0;i<n;++i){
            inilizer_list_temp.emplace_back(std::make_unique<Bar>());
        }
        return inilizer_list_temp;
    }
};
int main()
{
 Foo foo;
 for(auto const& item:foo.bars){
     std::cout << item->a;
 }
}

Live Demo

更多详情请查看Can I list-initialize a vector of move-only type?

编辑:

对于没有 std::make_uniuqe 的 C++11 用户:

template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
    return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}

Source

【讨论】:

  • 在我看来,问题的重点是避免循环并避免为每个实例输入 unique_pointer 创建逻辑。您的回答建议对一组唯一指针进行硬编码并从中移动,这与手动填写向量基本相同...
  • 与 2 配合得很好,那么 2000 呢?
  • 这看起来很有希望。如果我没有 C++14 支持怎么办? (我认为 std::make_unique 是 C++14 的特性)。
猜你喜欢
  • 2017-10-26
  • 1970-01-01
  • 2019-01-12
  • 1970-01-01
  • 2014-12-26
  • 1970-01-01
  • 2020-10-05
  • 1970-01-01
  • 2020-01-20
相关资源
最近更新 更多