如何在成员函数结束时绕过对析构函数的调用?

时间:2016-08-30 03:02:28

标签: c++ c++14

我有一个带有非平凡的非可复制(无论如何,可复制但非常昂贵)成员的结构,如果我打电话,我想要一个成员函数,它将转移成员的所有权。请参阅以下演示代码:

class A{
    // ...
};
struct s{
    A instance;
    A? take(){ // originally named get(), as mentioned in comment, for clarity
        return instance?;
    }
}; // Even after s is destroyed, instance should keep on

换句话说,我想延长instance的生命,然后在其他环境中使用它。我尝试了几种方法,包括return std::move(instance)或显式释放对象到一个临时变量,但没有一个工作。他们总是会调用实例的析构函数。

那么我怎样才能实现这一点,是否会返回const参考帮助?

3 个答案:

答案 0 :(得分:5)

  • 对象的生命周期不能扩展到其词法范围之外,除非它具有静态或线程存储持续时间。
  • 除了调用std::exit或以其他方式导致程序崩溃之外,你无法禁止对超出范围的对象进行隐式析构函数调用。

这看起来像XY problem。最有可能的是,实际的解决方案是让take()返回A(按值)并使用std::move将资源从s::instance移动到返回值,以便析构函数s::instance是无操作。

A take() {
    return std::move(instance);
}

但是,如果您不能告诉我们实际问题,我们无法确定。

答案 1 :(得分:0)

您需要正确设置实例的移动构造函数,以便它获取资源并将源保留为空shell。然后std :: move()会将成员转换为shell,并为您提供一个完整的对象,您可以执行所需的操作。析构函数仍将被调用,但基本上是一个无操作。

答案 2 :(得分:0)

实现这一目标的一种方法,即完全避免析构函数调用,是使用智能指针:

s

如果您希望默认构造的A包含s,请给s(): instance( new A ) {} 一个构造函数,例如:

A

如果需要,您可以使用完美转发将构造函数参数传递给A&#39的构造函数。

另一种可能的解决方案(我在前C ++ 11代码库中使用过)是给active一个名为{{1}}的可变布尔标志;然后让copy-constructor和copy-assignment操作符" move"操作期间的这个标志。然后析构函数只会破坏设置标志的实例的资源。但是在C ++ 11中,由于移动语义的可用性,这已经不再需要了。