0

假设我们有一个如下所示的类。

class DoStuffWithRef
{
    DoStuffWithRef(LargeObject& lo) : lo_(lo) {}

    // a bunch of member functions, some of them useful
    // [...]

private:
    LargeObject& lo_;
};

该类的设计使得唯一合理的用途是当至少一个其他实体拥有所lo_引用对象的所有权时。如果客户端代码适当地使用该类,则无需DoStuffWithRef拥有LargeObject.

如果类被滥用,有没有办法强制执行这种用法或发出错误信号?除了记录DoStuffWithRef?

例如,自动存储DoStuffWithRef可能指的是自动存储LargeObject

void foo()
{
    LargeObject lo;
    DoStuffWithRef dswr(lo);
    // some code that makes use of the DoStuffWithRef instance
    return;
}

这是我想到的主要用途,尽管在其他可能的情况下可以保证其他人拥有所有权。

问题是客户端代码很可能会创建一个DoStuffWithRef以悬空引用结束的实例。如果没有其他人拥有 aLargeObject所指的 a 的所有权,那么当试图访问DoStuffWithRef时就会出现混乱。更糟糕的是,只有在犯错很久之后才会出现混乱。DoStuffWithRefLargeObject

过去出现这种情况时,我使用 aboost::shared_ptr<>而不是引用(这是在 C++03 中)。这并不能恰当地表达类的语义。前提是DoStuffWithRef不需要所有权——它的目的是作用于他人拥有的对象,如果没有其他人拥有该对象,那么提供的功能DoStuffWithRef就没有意义了。授予所有权DoStuffWithRef具有不必要的开销并强制共享所有权语义。weak_ptr<>也会有错误的语义,因为我们不应该在运行时询问指针是否有效。

我从来没有在代码的性能敏感部分或共享所有权是一个重大负担的情况下出现这种情况,所以它并不重要,但我希望我知道一种在 C++ 中准确表达这一点的方法。成本很小,但它们也是不必要的。更重要的是,ashared_ptr<>会隐藏对类的不正确使用。如果DoStuffWithRef修改为使用 a 的 ashared_ptr<>是 a 的唯一剩余所有者LargeObject,则在短期内避免了悬空引用,但客户端代码最终处于未知领域。

4

1 回答 1

0

DoStuffWithRef 是否有其他状态?如果不是,它似乎是一堆实用函数。对 LargeObject 的引用也可以作为参数传递给每个函数。这也解决了所有权问题。

否则,如果它是有状态的,这显然是共享所有权的情况,因为 DoStuffWithRef 确实需要将 LargeObject 的单个活动实例的生命周期延长到其自身的生命周期。或者,使用弱指针并吃掉运行时检查的成本......

于 2015-01-19T06:55:59.860 回答