c++ - 如何在 OOP 中正确使用智能指针
问题描述
我想知道std::unique_ptr
在面向对象编程中使用的正确方法是什么。假设我有一个类,其中包含必须可以通过指针传递的成员对象
class B
{/*Some code here*/};
class A
{
public:
A();
B* getMember();
private:
std::unique_ptr<B> member
};
第一:成员应该是 astd::unique_ptr
还是 astd::shared_ptr
以避免内存泄漏?
其次,如果在我想要的情况下,我的 getter 的实施方式是什么
- 允许修改成员?
- 不允许修改成员?
我最初是这样做的:
B* A::getMember()
{
return member.get();
}
但我正在考虑让成员成为 astd::shared_ptr
并调整吸气剂:
class A
{
public:
A();
std::shared_ptr getMember();
private:
std::shared_ptr<B> member
};
std::shared_ptr A::getMember()
{
return member;
}
什么是标准和最广泛接受的实施方式?
解决方案
shared_ptr
意味着一个复杂的所有权规则,其中所讨论的对象由多个共同平等的方拥有,并且它的生命周期不容易确定。因为它更简单或更容易而决定使用shared_ptr
它就像使用火箭筒杀死困扰您的果蝇,因为它比苍蝇拍更强大。
在 C++ 中,没有简单的方法可以避免考虑所有权。
unique_ptr
提供简单的所有关系来管理生命周期。值类型(或具有值语义的类型)提供更简单的生命周期管理。int x=7;
没有人会对过去新手的一生感到困惑。
C++ 可以支持运行时多态值类型;见std::function
。如有疑问,请使用值。
class A {
public:
A();
B b;
};
更容易思考。
现在,如果您正在做类似 UI 框架的事情,那么您的 UI 元素将归您的框架所有。您可能需要一个命名系统、ASL 中的配置文件,以及一种将您的 UI 连接到操作并使用代码修改您的 UI 的方法。
旁边没有一个将涉及一个类,其成员子对象通过访问器返回指向它的指针。
也许您的 UI 是写入共享 ptr 数据的不可变副本,附加到您可以从框架获取/设置的名称。在这里,不可变数据是真正共享的;它就像一个整数。
无论如何,当您共享 B 指针时,您必须考虑 B 与 A 分开存在意味着什么,无论是哑、唯一、共享、不可变还是写入时复制。要么 B 成为 A 状态某些部分的接口,在这种情况下,它的生命周期在逻辑上是绑定的,要么它独立存在,在这种情况下,您可能需要值语义。
做出这个决定后,共享 ptr 可能是错误的生命周期规则。如果它是 A 状态的一部分的接口,那么共享所有权所暗示的它比 A 寿命更长是一个错误,如果它是您设置/获取的值,则获取它并修改状态隐式地充当 A 状态的接口!Sithout A 甚至知道!
A 正在从 B 传递状态更改通知?带上能拿到提供状态变化通知的B吗?明智的;在这里,B 可以是 UI 主题颜色,而 A 可以是控件。但是这里 A 可能有一个指向 const 主题颜色集的共享 ptr 以及一个主题更改消息的订阅令牌。(这里的颜色集是合法共享的)
简而言之,默认为共享 ptr 是不好的。当您无法使用值时,请使用唯一 ptr。所有权遵循生命周期,生命周期遵循语义。默认为值,C++ 是少数具有真正可靠的值支持的 OO 语言之一。
推荐阅读
- matlab - 如何在 Matlab 中查找和更改所有默认图形设置?
- certificate - vSphere 上的 OpenShift 4.5 IPI 安装无法使用自签名证书连接到 vCenter
- javascript - 点击事件监听器触发多次
- python - 与检测到的对象交互
- elasticsearch - 弹性搜索我所有的索引都显示为红色。可能是什么原因以及如何解决这个问题?
- python - 如何使用 Python 将 JSON 数据转换为 Avro 格式
- r - R条件两个变量的新变量
- for-loop - 使用 Windows 命令行 FOR 循环从文件中读取带有空格的路径
- microservices - 任何单体应用程序开发的设计实践可以轻松转换为微服务?
- javascript - if 语句中的 switch 语句未执行