簡體   English   中英

“ auto v = f()”和“ auto && v = f()”有什么區別?

[英]What's the difference between “auto v = f()” and “auto&& v = f()”?

#include <vector>

using namespace std;

vector<int> f()
{
    return{};
}

// Update: Below is not compilable
void g(vector<int>)
{}

// Update: Below is the my initial intent.
/*
void g(const vector<int>&)
{}
*/

void g(vector<int>&&)
{}

int main()
{
    auto       v1 = f();
    auto&& v2 = f();

    g(forward<vector<int>>(v1));
    g(forward<vector<int>>(v2));
}

C ++ 11是否保證g(forward<vector<int>>(v1))將調用f(vector<int>)f(const vector<int>&)g(forward<vector<int>>(v2))將調用f(vector<int>&&)嗎?

區別在於v1是向量,而v2是對向量的右值引用。

重載g你已經做的方式是一個非常糟糕的主意。 如果參數是cv不合格的右值,則調用將是模棱兩可的,因為兩個g都可以接受具有身份轉換序列的右值。 據,然而,可以接受的一個過載采取T&另取T&&

如果要轉發f()的值類別,請不要像復制到v1一樣復制/移動它。 這破壞了價值類別信息。 v1將始終是左值。

此外,您沒有正確使用std::forward v1v2都將強制轉換為右值引用,並且在這種情況下,在過載解析下的行為將相同。

以下是std::forward的正確用法:

void g(vector<int>&);
void g(vector<int>&&);
int main() {
    auto&& v1 = function_returning_lvalue_vector();
    auto&& v2 = function_returning_rvalue_vector();
    g(forward<decltype(v1)>(v1));  // calls lvalue overload
    g(forward<decltype(v2)>(v2));  // calls rvalue overload
}

有一個與返回值函數關聯的對象,稱為返回值 f()的返回值是vector<int>

在C ++ 11和C ++ 14中, f()按值返回:

  • auto v1 = f(); 使用copy / move構造函數從返回值初始化vector<int> ,將其稱為v1 這是一個復制省略上下文。
  • auto&& v2 = f(); 使名稱v2指定返回值,並延長了返回值的生存期。

如果編譯器確實實現了復制刪除,那么這兩個代碼具有相同的效果。 從C ++ 17開始,使用所謂的“保證復制省略”,這兩個代碼將相同。

“相同”是指在所有方面都相同,除了下面討論的decltype(identifier)的結果。


您的兩個g調用之間沒有區別。 在這兩種情況下,參數都是類型為std::vector的左值。 表達式 v1v2不會“記住”它們最初是否是返回值對象。

std::forward僅在給定了完美轉發推論的模板參數(因此可能是引用類型)時才有用。

建議使用decltype decltype(identifier)是一種特殊情況,它會在應用auto推論后重新調用標識符的聲明方式。

  • decltype(v1)vector<int>
  • decltype(v2)vector<int> &&

但是現在我們有了:

  • std::forward<decltype(v1)>vector<int> &&
  • std::forward<decltype(v2)>vector<int> &&

因此,您仍然不區分g的兩種不同形式。

實際上,如評論中所述,根本不可能調用g 每次通話都會模棱兩可。 在重載解析中,直接引用綁定是一種身份轉換。 類型的x值的參數T為參數相等匹配T作為T&& (類似地,類型T的左值參數對於參數TT&相等。)

重載g以實現左值vs.右值重載是可能的。 但是您也需要對v1的初始化進行更改:

void g(vector<int> const &) {}
void g(vector<int> &&) {}

// ...
auto const& v1 = f();
auto&& v2 = f();

g( std::forward<decltype(v1)>(v1) );
g( std::forward<decltype(v2)>(v2) );

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM