参考或shared_ptr为协会成员
Reference or shared_ptr as member for association
我正在写一个类栏。Bar 需要访问另一个类 Foo 才有用。因此,Foo的实例必须比使用它的Bar实例活得更久。
我无法在两种写法之间做出决定。下面是一个示例:
#include <iostream>
#include <memory>
using namespace std;
struct Foo {
Foo(int _x) : x_(_x) {}
~Foo() {}
int x_;
};
struct Bar1 {
Bar1(Foo& _foo) : foo_(_foo) {}
void print_foo() {cout << foo_.x_ << endl;}
private:
Foo& foo_;
};
struct Bar2 {
Bar2(shared_ptr<Foo> _foo) : foo_{move(_foo)} {}
void print_foo() {cout << foo_->x_ << std::endl;}
private:
shared_ptr<Foo> foo_;
};
int main()
{
Foo f1{1};
shared_ptr<Foo> f2 = make_shared<Foo>(2);
Bar1 b1(f1);
b1.print_foo();
Bar2 b2(f2);
b2.print_foo();
return 0;
}
我认为,Bar1 让用户在如何管理 Foo 的生命周期方面有了更大的自由度。而且它可能更有效率。但它进入一个未定义的(不确定是否这是正确的词)状态,当foo_所指的 Foo 实例被销毁时。
处理这种情况的首选方法是什么,为什么?
我认为处理这种情况的首选方法取决于情况的具体情况。 正如您所确定的,Bar1
在Foo
的生命周期内为用户提供了更多的自由,并且更加危险。 它也更有效(稍微),但可能不足以成为一个问题。
如果您知道一个事实(和/或可以证明)Foo
将始终比所有Bar
对象寿命长(也许您在main
中分配了在堆栈上使用的Foo
),那么使用 Bar1
没有问题。 如果您不确定,Bar2
将是要走的路。 尽管Bar2
的语义可能是错误的(也许你不希望Bar
让你的Foo
保持活力)。
这导致我们进入第三种选择: weak_ptr
. 这将让用户控制Foo
的生命周期,但仍然允许Bar
在Foo
被销毁时具有定义的行为。
struct Bar3 {
Bar3(std::weak_ptr<Foo> _foo) : foo_(_foo) {}
void print_foo_v1() {
// throws if foo_'s object has been destroyed
std::shared_ptr<Foo> foo(foo_);
std::cout << foo->x_ << std::endl;
}
void print_foo_v2() {
// returns nullptr if foo_'s object has been destroyed
std::shared_ptr<Foo> foo(foo_.lock());
if (foo) {
std::cout << foo->x_ << std::endl;
}
}
private:
std::weak_ptr<Foo> foo_;
};
如果您
知道Foo
会比使用基于引用的解决方案Bar
因为它简单且因为它表达了您想要实现的目标 - 那么 Bar 引用了 Foo。如果您使用指针,则意图并不那么明确。
相关文章:
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 助记符和指向成员语法的指针
- 用于访问容器<T>数据成员的正确 API
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 嵌套在类中时无法设置成员数据
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 将函数类成员映射到类本身内部
- 初始pointCloudt :: PTR类成员
- 通过成员函数将唯一 ptr 的向量附加到另一个向量
- LNK 2001 未解析的外部在 NPPluginFuncs 结构 ptr 作为静态类成员
- 我应该通过引用、值或ptr来存储一个完全封装的成员吗
- 从虚拟成员函数ptr中进行类型推导(bug?)
- 一个唯一的ptr类如何将它的实例指针传递给它的成员对象
- ptr到成员模板参数的友元语法