C++返回的引用生存期的提示/警告

C++ hinting/warning for returned reference lifetimes

本文关键字:警告 提示 引用 返回 C++ 生存期      更新时间:2023-10-16

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

// '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++用户做大多数不安全的事情,但是如果我至少可以对像这样的琐碎意外使用生成警告,那将是我想要实现的大部分。

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

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

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

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

你想让

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

与其

返回 B 的实例,是否可以在 A 上定义一个获取 B 然后将其传递给某种委托(虚拟方法、函子、lambda 函数)的方法?这样,user 函数就嵌套在对 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 一样长。