如何将"this"的生命周期移动到C++中的另一个对象中?



我想在C++中模拟 Rustbar(self, ...)函数,所以我写了这样的东西:

class Foo;
class Bar {
public:
explicit Bar(unique_ptr<Foo> foo);
private:
unique_ptr<Foo> _foo;
};
class Foo {
public:
Bar bar() {
return Bar(unique_ptr<Foo>(this));
}
};
Bar::Bar(unique_ptr<Foo> foo) : _foo(move(foo)) {}
TEST_CASE("Convert a Foo object into a Bar object") {
Bar b = Foo().bar();
}

此代码段将引发段错误。因为Foo()b都认为他们拥有Foo的实例,并且它将被清理两次。如何解决?


我将描述我想做什么。在下面的代码中:

auto foo = unique_ptr<Foo>(new Foo());
Bar b = some_func(move(foo));

在调用some_func之后,foo的生命周期被"转移"到some_func,我们不能再使用foo了。如果转换器函数继承了foo的资源,则应以这种方式设计b。在我的情况下,我希望some_func成为foo的实例方法。仅此而已。

我假设您希望测试用例中的这一行有效:

Bar b = Foo().bar();

你希望它的效果是b有一个std::unique_ptr<Foo>可以玩。

如果是这种情况,您将不得不实现bar来创建新的Fooinstace,因为Foo()是临时的,其生命周期无法以您想要的方式动态化。您在评论中提到Foo无法复制,但大概可以移动:

class Foo {
public:
Bar bar() && {
return Bar(std::make_unique<Foo>(std::move(*this)));
}
};

请注意,我使bar限定为右值限定,因此不能在左值上调用它(因为它从*this移动(。要在左值上调用它,您必须从中move

Foo().bar();  // rvalue calls are fine
Foo f;
std::move(f).bar();  // lvalue must be moved

您似乎混淆了 std::move 正在做什么,并假设它转移了对象所有权。 它没有。

std::move 所做的一切都是转换为右值引用,以便可以调用采用右值引用参数的适当函数。

据我所知,您无法从对象本身中延长对象的生存期。 在您提供的示例中,您正在创建一个类 Foo 的临时对象,一旦 bar(( 返回,该对象将被销毁。

您可以做的一件事是声明您的 some_func 函数以采用右值引用,如下所示:

Bar some_func(std::unique_ptr<Foo>&& someFoo)
{ 
Bar someBar(std::move(someFoo));
return someBar;
}
int main() {
auto foo = std::make_unique<Foo>();
//do stuff with foo
Bar b = some_func(std::move(foo));
//foo is now invalid, and can't be used;
//b has ownership of foo
return 0;
}

我不确定这是否回答了您的问题并做到了您的期望。要点是,您不是创建一个临时对象,而是创建一个具有make_unique的对象,并且您正在唯一指针周围移动您想要拥有您的实例的任何对象。

相关内容

  • 没有找到相关文章

最新更新