C ++提示/警告返回的参考生命周期

时间:2014-04-08 04:24:52

标签: c++ object-lifetime

我有一个不太理想的情况,即类返回对父对象生命周期后不应访问的对象的句柄引用。改变下面的模式以帮助防御性编码的最佳方法是什么?

// 'A<T>' is a thin factory-style utility class with asynchronous consumers.
template <typename T>
struct A {
  A() : h_(*(new T())) { /* ... */ }
  ~A() { /* h_ deleted or ownership passed elsewhere */ }

  // What's the best way to indicate that these handles shouldn't be used after
  // the destructions of the A instances?
  T &handle() { return h_; }

private
  T &h_;
};

struct B { /* ... */ };

int main() {
   B *b1{nullptr};
   {
     A<B> a;

     // Is there a good way to trigger detection that the reference is bound to
     // a variable which will outlive its 'valid' local lifetime?
     b1 = &a.handle();

     B &b2(a.handle()); // this is reasonable though

     b1->ok_action();
     b2.also_alright();
   }
   b1->uh_oh();
}

我知道你无法真正阻止C ++用户做出大多数不安全的事情,但如果我至少能够在琐碎的意外使用中产生警告,那么这将是我想要实现的大部分内容。 / p>

2 个答案:

答案 0 :(得分:1)

我冒昧地对你的情况作出一些假设:

  • 句柄指向A由用户自行决定生成的动态分配对象。
  • 句柄将在A超出范围的位置传递,因此A不能用作强制网关。
  • 销毁A时必须销毁句柄指向的数据,因此无法将自动垃圾收集应用于句柄。
  • 到目前为止,编译时安全检查似乎不可能。您希望编码错误在运行时通过某种异常机制而不是自发崩溃来表现出来。

考虑到这一点,这是一个可能的解决方案:

A的构造函数中,分配某种信号对象S,它在A被销毁时设置。使用S处理shared_ptr。让A::handle返回自定义句柄类H,其中包含B句柄和shared_ptrS。在H中创建一个解除引用运算符,用于验证A是否仍然有效(S未设置),或引发异常。当所有句柄过期时,S将自动销毁。

答案 1 :(得分:0)

你想让对象A产生另一个B类对象,让某人使用它,然后确保在A之前销毁B?

而不是返回B的实例,是否可以在A上定义一个获取B的方法,然后将其传递给某种委托(虚方法,仿函数,lambda函数)?这样,用户函数嵌套在对A方法上的方法的调用中,因此在用户代码完成任何操作之前,A在逻辑上不可能被销毁。

例如:

class A { public: template <typename Functor> void DoSomethingWithAnInstanceOfB(const char* whichB, Functor f) { B& bref = InternalLookupB(whichB); f(bref); } };

这会查找正确的B实例,然后将其传递给任意仿函数。仿函数可以做任何想做的事情,但必须在DoSomethingWithAnInstanceOfB()返回之前返回,因此保证A的生命周期至少与B一样长。