【问题标题】:How to move object from a function return correctly?如何正确地从函数返回中移动对象?
【发布时间】:2020-04-24 10:50:18
【问题描述】:

我有一个不应被复制而只能移动的对象,因此我试图确保函数返回对象的T&&。我的问题是对象在返回之前就被销毁了,我不知道如何正确地做到这一点。

#include <iostream>

class Foo
{public:
    Foo() { 
        a = new int; 
        std::cout << a << '\n'; 
    }
    Foo(const Foo& other) = delete;
    Foo(Foo&& other) { 
        a = other.a; other.a = nullptr; 
    }
    ~Foo() { 
        std::cout << a << '\n';
        delete a; 
    }
    void operator= (const Foo& other) = delete;
    void operator= (Foo&& other) { 
        a = other.a; 
        other.a = nullptr; 
    }
    int* a;
};

Foo&& createNewFoo()
{
    return std::move(Foo());
}

int main()
{
    Foo foo = createNewFoo(); // The pointer is deleted before this assigns to foo

}

【问题讨论】:

  • 顺便说一句。 void operator=() 看起来有点奇怪。我习惯了返回类型引用(即return *this;)。 Canonical implementations - Assignment operator
  • 继续 Scheff 所说的话。 void operator=() 是合法且允许的,但它是非惯用的,这增加了使用该对象的任何其他开发人员的摩擦。因为它会以令人惊讶和不寻常的方式表现。这是一个建议,不是规则以通常的方式执行,可能有充分的理由进行非典型实施。

标签: c++ c++11 return move temporary-objects


【解决方案1】:

您正在构造一个临时对象并将其绑定到右值引用作为返回值,该临时对象将在完整表达式后立即销毁,然后返回的引用始终悬空。

将函数更改为按值返回就可以了;右值将被移动到返回值。

Foo createNewFoo()
{
    return Foo();
}

顺便说一句:对于上面的代码,Foo foo = createNewFoo(); 不会复制/移动任何东西,因为copy elision,这是从 C++17 开始保证的。

编辑

那么为什么在返回return Foo();时临时不立即销毁

按值返回,返回顺序为

  1. 临时搭建
  2. 从临时移动构造返回值
  3. 临时被销毁

对于按引用返回,顺序是

  1. 临时搭建
  2. 将临时值绑定到返回值
  3. 临时被销毁
  4. 返回值(引用)变得悬空

【讨论】:

  • 那么为什么在返回时临时没有立即销毁 return Foo();引用是否在分配之前被销毁,而返回对象本身意味着在之后销毁它?
  • 我明白了。当您在这些步骤中说“返回值”时,您的意思是在将函数分配给 foo 之前从函数创建的临时值 Foo foo = createNewFoo();对?所以本质上,假设没有优化,按值返回,有一个从本地临时到返回值的移动,然后在 Foo foo = createNewFoo(); ?
  • @Zebrafish 是的,有 2 个动作(在 C++17 之前的概念中)。 (事实上​​两者都被省略了。)
【解决方案2】:

您只需执行以下操作:

static Foo createNewFoo() {
    return Foo();
}

由于Foo() 已经是一个右值,因此不需要std::move

【讨论】:

  • Foo() 不是右值引用!它根本不是参考。
  • @IgorR。对不起,我想快点写错了。答案已更新
猜你喜欢
  • 1970-01-01
  • 2018-03-01
  • 2012-02-02
  • 2022-01-18
  • 2011-02-03
  • 2015-07-31
  • 2015-12-15
  • 1970-01-01
  • 2011-10-29
相关资源
最近更新 更多