[英]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.