繁体   English   中英

在&&限定函数中返回右值引用和值之间的区别

[英]Difference between returning an rvalue reference and a value in && qualified functions

我最近看到了这个问题通过右值引用返回是否更有效? 并且注意到了评论链。 我正在评论链中寻找答案。

人们似乎说,在以下情况下,返回值应按右值引用而不是按值。 通过右值引用返回是否更有效?并且在任何情况下, 返回右值引用 (&&)都是有用的吗? )给出以下代码

#include <iostream>

using namespace std;

class Something {
public:
    Something() {
        cout << "Something()" << endl;
    }
    Something(const Something&) {
        cout << "Something(const Something&)" << endl;
    }
    Something(Something&&) {
        cout << "Something(Something&&)" << endl;
    }
};

class Maker {
public:
    Something get_something() && {
        return std::move(this->something);
    }
    const Something& get_something() & {
        return this->something;
    }

private:
    Something something;
};

int main() {
    auto maker = Maker{};
    auto something_one = maker.get_something();
    auto something_two = Maker{}.get_something();

    return 0;
}

Maker类中使用右值引用返回类型和常规值定义第一个方法有什么区别? 运行上面的代码可以按预期提供以下输出(该移动发生在函数调用中,返回之后该移动被忽略)

Something()
Something(const Something&)
Something()
Something(Something&&)

当我更改代码(即Maker类中的第一个方法)以返回右值引用时,我仍然得到相同的输出。 在这种情况下,为什么不只按价值返回?

当您以这种方式使用this参考限定词时,您必须问自己两个问题:

  1. std::move(object).funcname()是什么意思?
  2. Typename().funcname()是什么意思?

如果从函数返回一个值,则这两个都将表示同一件事。 不管您执行什么操作来捕获值,值都将是一个完整且与众不同的对象,它是由存储在对象中的一些内部数据移动构造而成的。

在第一种情况下, object现在可能不再拥有数据。 在第二种情况下,这并不重要,因为该对象是临时对象,此后已被销毁。

如果从函数中返回&& ,那么它们将具有不同的含义。 即,#2表示“您的代码已损坏”。

至于为什么您仍然想这样做,即使它允许代码损坏也是如此。 好吧,这与该问题的实际答案有关:这些东西什么意思

这就是我所指的。 std::get基本上是tuple的成员函数。 但是,如果将其传递给tuple&& ,则会得到T&&返回,而不是T 为什么?

因为您正在访问tuple成员

如果您具有struct ,则std::move(struct_object).x也将是右值引用。 因此, std::get对于tuple行为与对struct成员访问的行为相同。 毕竟,这就是tuple的全部要点:尽可能表现得像一个struct

这使您可以执行std::get<0>(std::move(tpl)).member ,这样该member仍将是右值引用。 因此,您可以从子对象移动而不会干扰对象的其余部分 ,这与您对任何其他右值引用成员的访问一样。

如果get返回一个值,那么这样做会大为不同。 无论我们如何处理返回值,它都将移出对象,而不会出现任何问题。 因此,如果我们只想移动该成员的子对象,那就太糟糕了。 原始对象失去了整个成员,而不仅仅是该成员的子对象。

当然,这不会改变以下事实:

auto &&x = SomeStruct().x; //This extends the temporary's lifetime
auto &&x = std::get<0>(SomeTuple(...)); //This gets a dangling reference.

这是语言的不幸限制。 但是,如果该函数是逻辑上的成员访问,然后返回一个&&&&胜任this功能,而不是一个值是合理的选择。

这完全取决于对您而言更重要的事情:安全性或与成员访问器的正交性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM