所有权不一致

Inconsistent Ownership

我有一个 class,直到此时它引用了另一个 class,因为它不拥有那个 class 并且不负责管理它的内存。

class MyClass
{
    OtherClass& m_other;
public:
    MyClass( OtherClass& other ) : m_other( other ) {}
};

然而,在某些情况下,MyClass 是 m_other 的所有者,我希望删除导致删除 OtherClass。在某些情况下,它不是所有者。

在这种情况下,用两个 class 表示两种情况更合适,还是用一个 class 封装两种情况(使用 unique_ptr)更合适。例如

class MyClassRef
{
    OtherClass& m_other;
public
    MyClassRef( OtherClass& other ) : m_other( other ) {}
};

class MyClassOwner
{
    std::unique_ptr<OtherClass> m_other; // Never null
public:
    MyClassOwner( std::unique_ptr<OtherClass> other ) : m_other( std::move( other ) ) {}
};

class MyClass
{
    OtherClass& m_other; // class may or may not be the one we manage.
    std::unique_ptr<OtherClass> m_managed; // May be null
public:
    MyClass( std::unique_ptr<OtherClass> managed ) : m_other( *managed ), m_managed( std::move( m_managed ) ) {}
    MyClass( OtherClass& other ) : m_other( other ), m_managed() {}
};

这可能是一个相当简单的示例,但一般来说,在处理拆分案例时,最好是创建新的 classes 来处理这些案例……还是将尽可能多的案例封装在一个 class - 达到合理水平。

编辑:与第二个选项类似的第三个选项是使用 std::shared_ptr<T> 例如

class MyClass
{
    std::shared_ptr<OtherClass> m_other;
public:
    MyClass( std::shared_ptr<OtherClass> other) : m_other( other ) {}
    MyClass( OtherClass& other ) : m_other( std::shared_ptr<OtherClass>( &other, []( OtherClass* p ){} ) ) {}
};

请注意,我希望 MyClass 仍然接受引用以允许指向堆栈分配对象的指针;这就是构造函数使用自定义删除器创建 shared_ptr<OtherClass> 不删除堆栈对象的原因。

当 class 在某些情况下可能是所有者,而在其他一些情况下它不是所有者时,您应该使用 std::shared_ptr<T>,这会维护 use count,代替 std::unique_ptr<T>,这需要资源的唯一所有权。

只要 m_other 指向的对象的所有引用都通过 std::shared_ptr<T> 智能指针维护,资源管理将为您自动完成,而不管拥有该对象的程序部分如何对象。