Jes*_*per 5 c++ smart-pointers c++11
如果这很简单,我很抱歉,但我已经玩了超过15年的C++.考虑这个简单的例子:向量包含类型的对象A.类B的A对象必须引用驻留在向量中的对象.(编辑说明 - 类B必须有一个引用该A实例的成员)
回到那一天你会宣布一个A*并完成它,但今天如何使用智能指针做到这一点?我不想在向量中存储共享或唯一指针,因为我不希望在堆上分配A对象.它们必须在矢量本身.
根据您的要求,您有几个选择.
A*在现代C++中拥有一个非拥有的原始指针没有错.如果B需要一个可以为空的引用,A并且A可以保证寿命比较长,B那么原始指针就完全可以了.引用可能需要为空的一个原因是,如果需要默认构造B,然后稍后设置引用:
class B {
A* a_ = nullptr;
public:
void setA(A& a) { a_ = &a; }
};
int main() {
std::vector<A> aVec(3);
B b;
b.setA(aVec[1]);
}
Run Code Online (Sandbox Code Playgroud)
A&如果引用不需要为空.如果在构造函数中设置引用B并且从不更改,那么您可以使用引用A&:
class B {
A& a_;
public:
B(A& a) : a_(a) {}
};
int main() {
std::vector<A> aVec (3);
B b(aVec[1]);
}
Run Code Online (Sandbox Code Playgroud)
std::reference_wrapper<A>使用引用的一个问题是您不能重新引用指向不同的引用,a这意味着您不能拥有setA成员函数,并且您不能拥有赋值运算符B::operator=(const B&).您可以使用非拥有的原始指针并强制原始指针永远不应为null.但是标准库现在提供了一个方便的方法std::reference_wrapper,它不能像引用那样为null,但可以像指针一样重新设置:
class B {
std::reference_wrapper<A> a_;
public:
B(A& a) : a_(a) {}
void setA(A& a) { a_ = a; }
};
int main() {
std::vector<A> aVec (3);
B b(aVec[1]);
B otherB(aVec[2]);
b = otherB; // use auto-generated assignment operator
b.setA(aVec[0]);
}
Run Code Online (Sandbox Code Playgroud)
vector一种常见的情况是,其中vector的A增长,所以它可能会重新分配和无效的引用,指针和迭代.在这种情况下,您可以将索引存储到vector.当vector增长时,该索引不会失效,也可以检查索引是否在向量的范围内而不是悬空:
class B {
std::vector<A>& aVec_;
int aIndex_;
public:
B(std::vector<A>& aVec, int aIndex) : aVec_(aVec), aIndex_(aIndex) {}
void useA() {
if (aIndex_ >= 0 && aIndex_ < aVec_.size()) {
auto& a = aVec_[aIndex_];
// use a ...
}
}
};
int main() {
std::vector<A> aVec (3);
B b(aVec, 1);
b.useA();
}
Run Code Online (Sandbox Code Playgroud)
如果您要添加和删除这些方法vector,A则这些方法都不起作用,您可能需要重新考虑您的设计.