【发布时间】:2015-03-17 01:24:59
【问题描述】:
假设我们有一个如下所示的类。
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 实例,该实例最终会产生一个悬空引用。如果没有其他人拥有由DoStuffWithRef 引用的LargeObject 的所有权,那么当DoStuffWithRef 尝试访问LargeObject 时就会出现混乱。更糟糕的是,只有在错误发生很久之后才会出现混乱。
当这在过去出现时,我使用了 boost::shared_ptr<> 而不是引用(这是在 C++03 中)。这并不能恰当地表达类的语义。前提是DoStuffWithRef 不需要所有权——它的目的是作用于他人拥有的对象,如果没有其他人拥有该对象,那么DoStuffWithRef 提供的功能就没有任何意义。将所有权授予DoStuffWithRef 会产生不必要的开销并强制共享所有权语义。 weak_ptr<> 也会有错误的语义,因为我们不应该在运行时询问指针是否有效。
我从来没有在代码的性能敏感部分或共享所有权是一个重大负担的情况下出现这种情况,所以这并不重要,但我希望我知道一种准确表达这一点的方法在 C++ 中。成本很小,但它们也是不必要的。更重要的是,shared_ptr<> 将隐藏该类的错误使用。如果修改为使用shared_ptr<> 的DoStuffWithRef 是LargeObject 的唯一剩余所有者,则在短期内避免了悬空引用,但客户端代码最终处于未知领域。
【问题讨论】:
-
A Proposal for the World's Dumbest Smart Pointer,将包含在c++17中。
标签: c++ smart-pointers ownership data-members