【发布时间】:2019-12-10 17:43:14
【问题描述】:
我正在构建 2 个类。 类 A 包含一个私有对象列表 obj_A,比如 list_a。 类 B 包含对象 obj_B 的列表,比如 list_b。 list_b 中的对象将指向 list_a 中的对象(并且需要访问数据但不修改)。 该类的基本版本如下所示:
#include <iostream>
#include <vector>
//obj_A contains data
class obj_A {
public:
obj_A(int x) {x_ = x;};
void print() const {
std::cout << "x_ = " << x_ << std::endl;
};
private:
int x_;
};
//A manages list of obj_A
class A {
public:
void addObj(obj_A obj_a) {
list_a_.push_back(obj_a);
};
obj_A* getObjPtr(int i) {
return &list_a_[i];
}
private:
std::vector<obj_A> list_a_;
};
//obj_B contains data related to obj_A
class obj_B {
public:
obj_B(obj_A * obj_a) : obj_a_(obj_a) {};
void printA() const {
obj_a_->print();
};
private:
const obj_A * obj_a_;
};
//B manages list of obj_B
class B {
public:
void addObj(obj_B obj_b) {
list_b_.push_back(obj_b);
};
void print() const {
for(auto b : list_b_) {
b.printA();
}
};
private:
std::vector<obj_B> list_b_;
};
//simple example
int main( int argc, char** argv ) {
//make A
obj_A a_obj_1(1);
obj_A a_obj_2(2);
A a;
a.addObj(a_obj_1);
a.addObj(a_obj_2);
//make B
obj_B b_obj_1( a.getObjPtr(0) );
obj_B b_obj_2( a.getObjPtr(0) );
obj_B b_obj_3( a.getObjPtr(1) );
B b;
b.addObj(b_obj_1);
b.addObj(b_obj_2);
b.addObj(b_obj_3);
//print stuff
b.print();
return 0;
}
据我了解,除非我使用智能指针,否则为单个对象(list_a 中的对象)创建多个指针(list_b 中的对象)是不好的做法。上面的代码是不好的做法吗?关于如何使用智能指针的任何建议?
【问题讨论】:
-
共享指针是否表示共享所有权?那么
std::shared_ptr可能很合适。否则,你能保证对象的生命周期至少和最后一个指向它的指针一样吗? -
“创建多个指向单个对象(list_a 中的对象)的指针(list_b 中的对象)是不好的做法,除非我使用智能指针”你从哪里得到的? raw vs smart 与其说你有多少指针,不如说谁拥有指向的对象
-
通常最好避免多个“拥有”指向单个对象的指针,因为它会混淆何时删除它。
shared_ptr有点帮助,但我仍然认为这是最后的手段,即使在带有垃圾收集的语言中,这样的事情也会让人困惑。如果您确实需要指针,单个所有者可以使用unique_ptr,这使得shared_ptr不需要的意图和生命周期变得清晰。 -
有点跑题了,但请记住,指向
std::vector中的对象的指针是危险的。当向量增加其容量时,它们都将失效。最好避免以在发生这种情况后最终可能会被使用的方式存储它们。 -
@Ralff
std::list没有同样的问题。插入或删除元素永远不会使指向列表中对象(被删除对象除外)的指针无效。另一种选择是存储指向std::vector本身的指针/引用以及索引。您使用哪种方法实际上取决于您的用例的具体情况。
标签: c++ oop pointers smart-pointers