簡體   English   中英

如果可能,C ++通過rvalue引用傳遞參數,否則復制左值引用

[英]C++ pass parameter by rvalue reference if possible, otherwise copy the lvalue reference

使用rvalue引用時,可能會省略許多冗余副本,但這似乎要求我多次寫入相同的函數(一個用於右值引用,一個用於const值左引用)。 但標准庫似乎只需要聲明一些函數。

例如:

#include <iostream>
#include <tuple>

void foo(int&& x){
    x = 2;
}

int main()
{
    int x = 1;
    foo(x); // compile error
    std::make_tuple(x); // ok
    std::cout << x << std::endl;
}

調用foo(x)是一個編譯錯誤,因為我無法從int隱式轉換為int&& 但我很困惑為什么std::make_tuple會起作用。 參考文獻表明它只接受右值參考參數。 當傳入它的值是ravlue引用時,它似乎也不會復制,但是當我在上面的示例中使用它時,它會復制(正如大多數人所期望的那樣)。

我怎么能讓foo像這樣工作?

該參考文獻表明它只接受右值參考參數。

不,這是轉發引用 ,根據傳入參數的值類別,它可以作為左值引用和右值引用。

我怎么能讓foo像這樣工作?

聲明轉發引用的要點是(1)類型推導是必要的,這意味着你需要在這里使foo成為一個函數模板; (2)參數x具有模板參數T的精確形式T&& 例如

template <typename T>
void foo(T&& x){
    x = 2;
}

然后

int x = 1;
foo(x);   // lvalue passed, T is deduced as int&, parameter's type is int&
foo(1);   // rvalue passed, T is deduced as int, parameter's type is int&&

請注意,對於std::make_tuple也是如此,即使它使用模板參數包也是如此。 更好的是要記住,即使轉發參考看起來像右值參考,但它們是不同的東西。

BTW: std :: forward通常與轉發引用一起使用,以保留參數的值類別,例如將其轉發給其他函數時。

std::make_tuple有效,因為該函數實際上並不像foo那樣采用右值引用。 std::make_tuple采用T&&形式的對象,因為T是模板類型,所以它使它成為轉發引用,而不是右值引用。 轉發引用可以綁定到左值和右值,其中右值引用只能采用右值。 使foo與你需要的一樣

template<typename T>
void foo(T&& bar)
{
    bar = 2;
}

這對你有用嗎?

#include <iostream>
#include <tuple>

void foo(int&& x){
    std::cout<<"rvalue"<<std::endl;
    x = 2;
}

void foo(int& x){
    std::cout<<"lvalue"<<std::endl;
    x = 2;
}

int main()
{
    int x = 1;
    foo(x); // no compile error anymore
    foo(std::move(x)); // now r-value is being used        
    std::make_tuple(x); // ok
    std::cout << x << std::endl;
}

差異是&&運算符與模板參數一起使用時相當微妙的重載的結果:

template<typename foo>
void bar(foo &&baz)

這不是右值參考。 它是轉發參考。 當模板得到解析時, baz將是左值或右值引用,具體取決於調用情況。

這就是為什么你會看到C ++庫提供看似單個模板的原因,它在lvalue和rvalue上下文中都有效。

但轉發引用僅出現在模板中。 在非模板聲明中:

void bar(int &&baz)

這始終是rvalue引用,並且只能在rvalue上下文中使用。

暫無
暫無

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

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