在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
答案 0 :(得分: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";
<{1}}无法使用 resize()
,因为它不是默认构造的。但是,此解决方案很脆弱,因为std::reference_wrapper<CanNotCopy>
引用的和 CanNotCopy
实例中引用的int
存在生命依赖性,存在悬空引用的风险。
解决方案是使用std::unique_ptr<CanNotCopy>
作为元素类型(可移动且默认可构造):
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
引用的生命周期依赖性仍然存在。
答案 1 :(得分:0)
直截了当,允许vector<CanNotCopy>
:
struct CanNotCopy {
int& intref_;
CanNotCopy (CanNotCopy && from) : intref_(from.intref_) { }
};
这当然允许您将对象移入和移出向量,但不能创建副本或创建默认构造的元素。我不知道该类的语义,特别是我不知道intref_
的意思。你必须在默认的ctor中初始化它,所以我不能为你写。
答案 2 :(得分:0)
可以通过使用std::optional
/ boost::optional
包装器来实现。第二个要求使用in-place factories来实现所需的行为。
答案 3 :(得分:0)
我有同样的问题得到了很好的回答here:使用std::vector::emplace_back
。