簡體   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