我有一个带有非平凡的非可复制(无论如何,可复制但非常昂贵)成员的结构,如果我打电话,我想要一个成员函数,它将转移成员的所有权。请参阅以下演示代码:
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参考帮助?
答案 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中,由于移动语义的可用性,这已经不再需要了。