0

是否可以在 C++11 中拥有没有可复制对象(具有引用实例)的 std::vector ?

struct CanNotCopy {
  int& intref_;
  CanNotCopy(int& i) noexcept : intref_(i) {}
  // How do I make move constructor and operator = ?
};

std::vector<CanNotCopy> hoge; // OK
hoge.resize(10); // default constructor required
int j = 123;
hoge[1] = CanNotCopy(j);  // copy constructor required
4

4 回答 4

5

std::vector, 描述T:

对元素施加的要求取决于对容器执行的实际操作。一般要求元素类型满足 MoveConstructible 和 MoveAssignable 的要求,但很多成员函数的要求更严格。

CanNotCopy不可移动或可复制,因此不能用作T.

部分解决方案是std::reference_wrapper<CanNotCopy>用作元素类型(可复制但不可默认构造),它:

...是一个类模板,它将引用包装在可复制、可分配的对象中。它经常被用作在标准容器(如 std::vector 或 std::pair)中存储引用的机制,这些容器通常不能保存引用。

例如:

std::vector<std::reference_wrapper<CanNotCopy>> hoge;
int j = 19;
CanNotCopy c(j);
hoge.push_back(std::ref(c));
std::cout << hoge[0].get().intref_ << "\n";

resize()不可用,std::reference_wrapper<CanNotCopy>因为它不是默认可构造的。但是,此解决方案很脆弱,因为实例中的CanNotCopy引用int引用存在生命周期依赖关系,CanNotCopy存在悬空引用的风险。

一种解决方案是std::unique_ptr<CanNotCopy>用作元素类型(可移动且默认可构造):

std::vector<std::unique_ptr<CanNotCopy>> hoge;
hoge.resize(5);
int j = 19;
hoge[1].reset(new CanNotCopy(j));
std::cout << hoge[1]->intref_ << "\n";

int尽管如此,对内部引用的生命周期依赖CanNotCopy仍然存在。

于 2013-06-06T08:09:26.590 回答
0

直截了当,允许vector<CanNotCopy>

struct CanNotCopy {
  int& intref_;
  CanNotCopy (CanNotCopy && from) : intref_(from.intref_) { }
};

当然,这将允许您将对象移入和移出向量,但不能创建副本或创建默认构造的元素。我不知道类的语义,特别是我不知道是什么intref_意思。你也必须在默认的ctor中初始化它,所以我不能为你写。

于 2013-06-06T11:47:47.287 回答
0

这可以通过使用std::optional/boost::optional包装器来实现。第二个需要使用就地工厂来实现所需的行为。

于 2013-11-06T10:54:36.847 回答
0

我有同样的问题,在这里得到了很好的回答:使用std::vector::emplace_back

于 2013-11-09T07:51:16.053 回答