如何获得对右值的引用?
How is it possible to get a reference to an rvalue?
我在 C++ 中使用过 std::move
和 std::forward
。我的问题是:标准库实际上是如何实现这些功能的?
如果左值是您可以获得其地址的东西,而右值完全不是左值,那么您如何实际实现这些引用?
这些新设施是否允许这样的事情:
auto x = &(3);
之类的?你能得到一个右值的引用,而不仅仅是 std::move
/forward
返回的左值吗?
希望这些问题是有道理的。我找不到关于 Google 的好资料,只有关于完美转发的教程等
基本上,编译器魔法。标准描述了规则,编译器制造者只需要弄清楚如何实现规则。
在实践中,引用要么被优化掉,要么实现为 CPU 级别的指针。
std::move
在这个意义上并不是特别的。它有一个左值引用作为输入,一个右值引用作为输出。编译器只需将右值引用规则应用于输入。
类似地,std::forward<T>
的目标只是告诉编译器对参数应用一组不同的规则,这些规则恰好被定义以便完美转发工作。函数本身什么都不做。
How is it possible to get a reference to an rvalue?
从概念上讲,rvalue 表达式创建一个临时对象,或者有时表示一个现有对象。它可以像任何其他对象一样绑定到引用;但是,为了避免混淆,该语言只允许 rvalue 和 const
lvalue 引用。
I have used std::move and std::forward in C++. My issue is how this is actually implemented by the compiler?
move
只是 return 一个 rvalue 对其参数的引用,相当于
static_cast<typename remove_reference<T>::type&&>(t)
函数调用的结果是一个rvalue(具体来说,是一个xvalue),所以它可以绑定到一个rvalue 函数参数不能引用的地方。这允许您明确地从 lvalue 移动,使用 move
将其转换为 rvalue,同时不允许您意外移动来自它。
forward
类似,但重载到 return rvalue 对 rvalue 或 rvalue 引用,以及 lvalue 对其他任何内容的引用。
If an l-value is something you can get the address of
这或多或少是正确的。官方定义是表达式"designates a function or an object",那些是有地址的东西。
and an r-value is exclusively not an l-value
不是真的。稍微简化一下,表达式可以是 lvalue 或 rvalue,但可以从一个转换为另一个。 lvalue 可以隐式转换为 rvalue;转换另一种方式可以通过转换来完成,就像 move
那样。
how can you actually implement these references?
就像任何其他引用一样 - 作为它绑定到的对象的别名或指针。唯一的区别是可以使用哪种表达式来表示(并可能创建)绑定到引用的对象。
Do these new facilities allow for something like auto x = &(3);
它试图直接获取 rvalue 的地址,这是不允许的。由于问题是关于引用而不是指针,因此允许以下内容,将引用绑定到临时对象(其生命周期延长以匹配引用):
auto && rvalue = 3;
auto const & const_lvalue = 3;
虽然不允许将其绑定到非常量 左值 引用
auto & lvalue = 3; // ERROR
我无法像这样调用函数:void foo(string* bar)
:foo(&string("Hello World!"))
否则会出现错误:
error: taking address of temporary
我也不能像这样调用函数:void foo(string& bar)
:foo(string("Hello World!"))
否则我会收到错误消息:
error: invalid initialization of non-const reference of type 'std::string& {aka std::basic_string&}' from an rvalue of type 'std::string {aka std::basic_string}'
C++11 为我提供的能力是创建一个右值引用,所以我可以 调用一个函数:void foo(string&& bar)
像这样:foo(string("Hello World!"));
此外,在内部foo
我可以获取右值引用传入的对象的地址:
void foo(string&& bar){
string* temp = &bar;
cout << *temp << " @:" << temp << endl;
}
OP 似乎对右值有很好的把握。但是 this explanation of them 对我有帮助,可能对其他人也有帮助。它详细介绍了为什么 C++03 允许常量引用右值,而 C++11 的右值引用。
我在 C++ 中使用过 std::move
和 std::forward
。我的问题是:标准库实际上是如何实现这些功能的?
如果左值是您可以获得其地址的东西,而右值完全不是左值,那么您如何实际实现这些引用?
这些新设施是否允许这样的事情:
auto x = &(3);
之类的?你能得到一个右值的引用,而不仅仅是 std::move
/forward
返回的左值吗?
希望这些问题是有道理的。我找不到关于 Google 的好资料,只有关于完美转发的教程等
基本上,编译器魔法。标准描述了规则,编译器制造者只需要弄清楚如何实现规则。
在实践中,引用要么被优化掉,要么实现为 CPU 级别的指针。
std::move
在这个意义上并不是特别的。它有一个左值引用作为输入,一个右值引用作为输出。编译器只需将右值引用规则应用于输入。
类似地,std::forward<T>
的目标只是告诉编译器对参数应用一组不同的规则,这些规则恰好被定义以便完美转发工作。函数本身什么都不做。
How is it possible to get a reference to an rvalue?
从概念上讲,rvalue 表达式创建一个临时对象,或者有时表示一个现有对象。它可以像任何其他对象一样绑定到引用;但是,为了避免混淆,该语言只允许 rvalue 和 const
lvalue 引用。
I have used std::move and std::forward in C++. My issue is how this is actually implemented by the compiler?
move
只是 return 一个 rvalue 对其参数的引用,相当于
static_cast<typename remove_reference<T>::type&&>(t)
函数调用的结果是一个rvalue(具体来说,是一个xvalue),所以它可以绑定到一个rvalue 函数参数不能引用的地方。这允许您明确地从 lvalue 移动,使用 move
将其转换为 rvalue,同时不允许您意外移动来自它。
forward
类似,但重载到 return rvalue 对 rvalue 或 rvalue 引用,以及 lvalue 对其他任何内容的引用。
If an l-value is something you can get the address of
这或多或少是正确的。官方定义是表达式"designates a function or an object",那些是有地址的东西。
and an r-value is exclusively not an l-value
不是真的。稍微简化一下,表达式可以是 lvalue 或 rvalue,但可以从一个转换为另一个。 lvalue 可以隐式转换为 rvalue;转换另一种方式可以通过转换来完成,就像 move
那样。
how can you actually implement these references?
就像任何其他引用一样 - 作为它绑定到的对象的别名或指针。唯一的区别是可以使用哪种表达式来表示(并可能创建)绑定到引用的对象。
Do these new facilities allow for something like
auto x = &(3);
它试图直接获取 rvalue 的地址,这是不允许的。由于问题是关于引用而不是指针,因此允许以下内容,将引用绑定到临时对象(其生命周期延长以匹配引用):
auto && rvalue = 3;
auto const & const_lvalue = 3;
虽然不允许将其绑定到非常量 左值 引用
auto & lvalue = 3; // ERROR
我无法像这样调用函数:void foo(string* bar)
:foo(&string("Hello World!"))
否则会出现错误:
error: taking address of temporary
我也不能像这样调用函数:void foo(string& bar)
:foo(string("Hello World!"))
否则我会收到错误消息:
error: invalid initialization of non-const reference of type 'std::string& {aka std::basic_string&}' from an rvalue of type 'std::string {aka std::basic_string}'
C++11 为我提供的能力是创建一个右值引用,所以我可以 调用一个函数:void foo(string&& bar)
像这样:foo(string("Hello World!"));
此外,在内部foo
我可以获取右值引用传入的对象的地址:
void foo(string&& bar){
string* temp = &bar;
cout << *temp << " @:" << temp << endl;
}
OP 似乎对右值有很好的把握。但是 this explanation of them 对我有帮助,可能对其他人也有帮助。它详细介绍了为什么 C++03 允许常量引用右值,而 C++11 的右值引用。