简体   繁体   English

OOP中如何正确使用智能指针

[英]How to correctly use smart pointers in OOP

I am wondering what is the correct way to use std::unique_ptr in an Object-Oriented Programming.我想知道在面向对象编程中使用std::unique_ptr的正确方法是什么。 Let's say I have a class that contains an member object that can be passed by pointer假设我有一个 class 包含一个可以通过指针传递的成员 object

class B
{/*Some code here*/};

class A
{
public:
    A();
    B* getMember();
private:
    std::unique_ptr<B> member
};

First: Should the member be a std::unique_ptr or a std::shared_ptr to avoid memory leaks?第一:成员应该是std::unique_ptr还是std::shared_ptr以避免 memory 泄漏?

Second, what would be the implementation of my getter if in cases where I want to其次,如果在我想要的情况下,我的 getter 的实施方式是什么

  1. Allow modification of the member?允许修改成员?
  2. Not allow modification of the member?不允许修改成员?

I initially did:我最初是这样做的:

B* A::getMember()
{
    return member.get();
}

But I am considering to have the member be a std::shared_ptr and adapt the getter:但我正在考虑让成员成为std::shared_ptr并调整 getter:

class A
{
public:
    A();
    std::shared_ptr getMember();
private:
    std::shared_ptr<B> member
};

std::shared_ptr A::getMember()
{
    return member;
}

What is the standard and most-widely accepted implementation?什么是标准和最广泛接受的实施方式?

shared_ptr implies a complex ownership rule where the object in question is owned by multiple co-equal parties, and its lifetime cannot be determined easily. shared_ptr意味着一个复杂的所有权规则,其中所讨论的 object 由多个平等方拥有,并且其生命周期不容易确定。 Deciding to go with shared_ptr because it is simpler or easier is like using a bazooka to kill a fruit fly bothering you because it is more powerful than a fly swatter.决定使用shared_ptr的 go 因为它更简单或更容易,就像使用火箭筒杀死困扰您的果蝇一样,因为它比苍蝇拍更强大。

In C++ there is no simple way to avoid thinking about ownership.在 C++ 中,没有简单的方法可以避免考虑所有权。

unique_ptr provides a simple owned-by relationship to manage lifetimes. unique_ptr提供了一个简单的拥有关系来管理生命周期。 Value types (or types with value semantics) provide even simpler lifetime management.值类型(或具有值语义的类型)提供更简单的生命周期管理。 Nobody gets confused by the lifetime of int x=7;没有人会对int x=7; past a novice.过去一个新手。

C++ can support runtime polymorphic value types; C++可以支持运行时多态值类型; see std::function .std::function When in doubt use values.如有疑问,请使用值。

class A {
public:
  A();
  B b;
};

far easier to think about.更容易思考。

Now, if you are doing something like a UI framework, then your UI elements are going to be owned by your framework.现在,如果您正在做类似 UI 框架的事情,那么您的 UI 元素将归您的框架所有。 You'll probably want a naming system, configuration files in an ASL, and a way to connect your UI to actions and modify your UI with code.您可能需要一个命名系统、ASL 中的配置文件,以及一种将您的 UI 连接到操作并使用代码修改您的 UI 的方法。

Next to none of this will involve a class with a member subobject returning pointers to it via accessors.旁边没有一个将涉及一个 class ,其成员子对象通过访问器返回指向它的指针。

Maybe your UI is immutable copy on write shared ptr data attached to names you can get/setfrom the framework.也许您的 UI 是写入共享 ptr 数据的不可变副本,附加到您可以从框架获取/设置的名称。 Here the immutable data is truely shared;在这里,不可变数据是真正共享的; it acts like an integer.它的作用类似于 integer。

Regardless, you have to think about what it means for a B to exist seperate from an A whenever you share a B pointer, be it dumb, unique, shared, immutable or copy on write.无论如何,当您共享 B 指针时,您必须考虑 B 与 A 分开存在意味着什么,无论是哑、唯一、共享、不可变还是写入时复制。 Either B becomes some interface to some part of A's state, in which case its lifetime is logically tied, or it lives independently, in which case you probably want value semantics. B 成为 A 的 state 的某些部分的某个接口,在这种情况下,它的生命周期在逻辑上是相关的,或者它独立存在,在这种情况下,您可能需要值语义。

And having made that decision, a shared ptr is probably the wrong lifetime rule.做出这个决定后,共享 ptr 可能是错误的生命周期规则。 If it is an interface to part of A's state, it outliving A as implied by shared ownership is an error, and if it is a value you set/get, getting it and modifying the state implicitly acts as an interface to A's state!如果它是 A 的 state 的一部分的接口,则它比共享所有权暗示的 A 寿命更长是一个错误,如果它是您设置/获取的值,获取它并修改 state 隐式充当 A 状态的接口! Sithout A even knowing! Sithout A 甚至知道!

A being deliver ed state change notifications from a B? A 正在交付 state 来自 B 的更改通知? Bring able to get the B that provides state change notifications?带上能拿到提供state变更通知的B吗? Sensible;明智的; here, B could be UI theming colour, and A a control.在这里,B 可以是 UI 主题颜色,而 A 可以是控件。 But here A probably has a shared ptr to a const theme color set plus a subscription token to theme change messages.但是这里 A 可能有一个指向 const 主题颜色集的共享 ptr 以及一个主题更改消息的订阅令牌。 (here the colour set is legitimately shared) (这里的颜色集是合法共享的)

In short, defaulting to shared ptr is bad.简而言之,默认为共享 ptr 是不好的。 Use unique ptr when you cannot use values.当您无法使用值时,请使用唯一 ptr。 Ownership follows lifetime, which follows from semantics.所有权遵循生命周期,生命周期遵循语义。 Default to values, C++ is one of the few OO languages that has really solid value support.默认为值,C++ 是少数具有真正可靠的值支持的 OO 语言之一。

If you're handing out pointers to a unique_ptr then you're not really treating it as "unique".如果您正在分发指向unique_ptr的指针,那么您并没有真正将其视为“唯一”。

What you really need is a shared_ptr .您真正需要的是shared_ptr Your second approach is the correct way.您的第二种方法是正确的方法。 These are intended to be copied as necessary and retain reference counts.这些旨在根据需要复制并保留引用计数。 This means so long as you hold a copy of the shared_ptr object, you're able to access it.这意味着只要您持有shared_ptr object 的副本,您就可以访问它。

In the former case you have absolutely no clue if your pointer is still valid after the instant you receive it.在前一种情况下,您完全不知道您的指针在收到它的那一刻之后是否仍然有效。 You must manually track that, which is sort of defeating the point of using smart pointers.您必须手动跟踪它,这有点违背使用智能指针的目的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM