c++ - vector<unique_ptr<A>> 使用初始化列表

标签 c++ c++11 constructor containers unique-ptr

我遇到了一个错误:调用'std::__1::unique_ptr >'的隐式删除复制构造函数时使用类似于下面的编译代码 c++ -std=c++14 unique_ptr_vector.cpp -o main

这是一个简化的版本:

头文件“my_header.h”:

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

class A{
public:
    A() : n(0) {}
    A(int val) : n(val) {} 
    A(const A &rhs): n(rhs.n) {}
    A(A &&rhs) : n(std::move(rhs.n)) {}
    A& operator=(const A &rhs) { n = rhs.n; return *this; }
    A& operator=(A &&rhs) { n = std::move(rhs.n); return *this; }
    ~A() {}

    void print() const { std::cout << "class A: " << n << std::endl; }
private:
    int n;
};

namespace {
    std::vector<std::unique_ptr<A>> vecA = {
        std::make_unique<A>(1),
        std::make_unique<A>(2),
        std::make_unique<A>(3),
        std::make_unique<A>(4)
    };
}

还有我的源文件unique_ptr_vector.cpp :

#include "my_header.h"

using namespace std;

int main()
{
    for(const auto &ptrA : vecA){
        ptrA->print();
    }
    return 0;
}

我真的需要使用 push_back(std::make_unique<A>(<some_number>)) 吗?分别针对每个组件, 或者在 header 中填充容器的首选方法是什么?或者这通常是个坏主意?

我见过类似 this one 的问题, this one , 和 this one .

我现在知道初始化列表似乎是不可能的。但是人们通常用container<unique_ptr>做什么.我是否应该简单地避免在 header 中初始化它...

最佳答案

初始化列表是 const 数组的包装器。

unique_ptrconst 无法移动。

我们可以像这样(以完全合法的方式)解决这个问题:

template<class T>
struct movable_il {
  mutable T t;
  operator T() const&& { return std::move(t); }
  movable_il( T&& in ): t(std::move(in)) {}
};

template<class T, class A=std::allocator<T>>
std::vector<T,A> vector_from_il( std::initializer_list< movable_il<T> > il ) {
  std::vector<T,A> r( std::make_move_iterator(il.begin()), std::make_move_iterator(il.end()) );
  return r;
}

Live example .

使用:

auto v = vector_from_il< std::unique_ptr<int> >({
  std::make_unique<int>(7), 
  std::make_unique<int>(3)
});

如果您想知道为什么初始化程序列出引用 const 数据,您必须查找并阅读委员会 session 记录或询问当时在场的人。我猜这是关于最小意外原则和/或对可变数据和 View 类型有疑虑的人(例如将 array_view 重命名为 span)。

如果你想要的不仅仅是 vector :

template<class C, class T=typename C::value_type>
C container_from_il( std::initializer_list< movable_il<T> > il ) {
  C r( std::make_move_iterator(il.begin()), std::make_move_iterator(il.end()) );
  return r;
}

它仍然需要按摩才能与关联容器一起工作,因为我们还想移动键。

template<class VT>
struct fix_vt {
  using type=VT;
};
template<class VT>
using fix_vt_t = typename fix_vt<VT>::type;
template<class VT>
struct fix_vt<const VT>:fix_vt<VT>{};
template<class K, class V>
struct fix_vt<std::pair<K,V>>{
  using type=std::pair<
    typename std::remove_cv<K>::type,
    typename std::remove_cv<V>::type
  >;
};

template<class C, class T=fix_vt_t<typename C::value_type>>
C container_from_il( std::initializer_list< movable_il<T> > il ) {
  C r( std::make_move_iterator(il.begin()), std::make_move_iterator(il.end()) );
  return r;
}

关于c++ - vector<unique_ptr<A>> 使用初始化列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46737054/

相关文章:

C++如何在不丢失内存的情况下删除节点?

c++ - 分段如何提高埃拉托色尼筛法的运行时间?

c++ - MingW 上更新的 G++ 收到大量错误消息

c++ - 比较具有替代顺序的自定义类型的 std::tuple(或 std::pair)。是否可以插入自定义小于/比较函数?

c++11 - 如何在另一个命名空间中使用一个命名空间的指针,并且两个命名空间都在另一个类中使用

C++ 显式构造函数

.net - 构造函数优先级

c++ - 在 vector 的 vector 中查找元素的位置

c++ - 为什么在调用 std::vector::emplace_back() 时调用复制构造函数?

javascript - 为什么用构造函数创建对象会执行JavaScript中对象的方法?