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

How to move lifetime of "this" into another object in C++?

我想在 C++ 中模拟 Rust bar(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的生命周期为"transferred"到some_func,我们不能再使用foo了。如果 b 继承了 foo 的资源,转换器函数应该这样设计。在我的情况下,我希望 some_func 成为 foo 的实例方法。就是这样。

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

Bar b = Foo().bar();

你希望它的效果是 b 得到一个 std::unique_ptr<Foo> 来玩。

如果是这种情况,您将必须实施 bar 来创建 Foo 的新实例,因为 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所做的一切都是转换为右值引用,以便可以调用采用右值引用参数的适当函数。

据我所知,您不能从对象本身延长对象的生命周期。 在您提供的示例中,您正在创建 class Foo 的临时对象,它将在 bar() returns.

后立即销毁

您可以做的一件事是声明您的 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 创建一个对象,并且您正在围绕唯一指针移动到您想要拥有您的实例的任何对象。