如果可能,C++按右值引用传递参数,否则复制左值引用
C++ pass parameter by rvalue reference if possible, otherwise copy the lvalue reference
对于右值引用,可以省略许多冗余副本,但这似乎需要我多次编写相同的函数(一个用于右值引用,一个用于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
,即使它使用模板参数包也是如此。最好记住,即使是转发引用看起来像右值引用,但它们是不同的东西。
顺便说一句:std::forward 通常与转发引用一起使用,以保留参数的值类别,例如将其转发到其他函数时。
这种差异是由于 &&
运算符与模板参数一起使用时相当微妙的重载造成的:
template<typename foo>
void bar(foo &&baz)
这不是右值引用。它是一个转发引用。解析模板后,baz
将是左值或右值引用,具体取决于调用情况。
这就是为什么您将看到C++库提供了看似单个模板的内容,该模板在左值和右值上下文中都有效。
但转发引用仅发生在模板中。在非模板声明中:
void bar(int &&baz)
这始终是右值引用,只能在右值上下文中使用。
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;
}
- 将const引用参数初始化为默认参数会导致悬空引用吗
- 具有常量引用参数的函数模板专用化
- C++:常量引用参数
- 字符串引用参数的效率C++
- 通过非常量引用参数修改常量引用参数
- 如何将指针变量作为引用参数传递?
- C++初始化 std::function 时如何将占位符绑定到引用/引用参数?
- 移动类的成员作为常量引用参数传递
- C++带有适用于左值和右值的引用参数的函数
- constexpr 函数的常量引用参数:gcc/msvc vs clang/icc
- 如何使用类型特征将函数的通用引用参数限制为 r 值引用?
- 委托构造函数和引用参数
- 对 const 引用参数使用默认值会导致崩溃
- 为什么我们不允许将纯引用参数传递给 std::thread,但允许传递原始指针?
- 为什么我需要将默认引用参数定义为 const 以便为其分配一个左值?
- 将非左值作为常量引用参数传递.临时是在本地作用域还是在调用方作用域中创建的?
- 如何强制函数仅接受左值引用参数
- 模板引用参数推断失败C++
- 非类型引用参数可以在运行时修改,这是否意味着模板可以在运行时实例化?
- 将unique_ptr作为引用参数或常量传递unique_ptr引用