首页 > 解决方案 > 如何在 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 的实施方式是什么

  1. 允许修改成员?
  2. 不允许修改成员?

我最初是这样做的:

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;
}

什么是标准和最广泛接受的实施方式?

标签: c++shared-ptrunique-ptr

解决方案


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 语言之一。


推荐阅读