[英]What does the address of an lvalue reference to a prvalue represent?
When a function parameter is of type lvalue reference lref
: 当函数参数的类型为lvalue reference
lref
:
void PrintAddress(const std::string& lref) {
std::cout << &lref << std::endl;
}
and lref
is bound to a prvalue: 和
lref
绑定到prvalue:
PrintAddress(lref.substr() /* temporary of type std::string */)
what does the address represent? 地址代表什么? What lives there?
那里住着什么?
A prvalue cannot have its address taken. prvalue无法获取其地址。 But an lvalue reference to a prvalue can have its address taken, which is curious to me.
但是对 prvalue的左值引用可以得到它的地址,这对我很好奇。
Inside the function lref
is not a prvalue it is an lvalue and you can take the address of it. 在函数内部,
lref
不是prvalue,它是一个左值,你可以获取它的地址。
There is a common misconception about rvalues vs. lvalues. 关于右撇子与左撇子有一个共同的误解。 A named parameter is always an lvalue.
命名参数始终是左值。 No matter whether it is a reference type that is bound to an rvalue.
无论它是否是绑定到右值的引用类型。 Through a
const &
reference type you can't even tell which kind of value category the object actually has at the point where the function is called. 通过
const &
引用类型,您甚至无法分辨对象在调用函数时实际具有哪种值类别。 Rvalue references and non-const Lvalue references give you that information: Rvalue引用和非const Lvalue引用为您提供以下信息:
void foo(std::string& L, std::string&& R)
{
// yeah i know L is already an lvalue at the point where foo is called
// R on the other hand is an rvalue at the point where we get called
// so we can 'safely' move from it or something...
}
The temporary string is a prvalue in the context of the caller (at the point PrintAddress
is called). 临时字符串是调用者上下文中的prvalue(在调用
PrintAddress
)。 Within the context of the callee (in PrintAddress
) lref
is an lvalue reference because in this context it actually is an lvalue. 在被调用者的上下文中(在
PrintAddress
), lref
是左值引用,因为在此上下文中它实际上是左值。
PrintAddress
isn't aware of the limited lifetime of the passed argument and from PrintAddress
' point of view the object is "always" there. PrintAddress
不知道传递参数的有限生命周期,并且从PrintAddress
的角度来看,对象“始终”存在。
std::string q("abcd");
PrintAddress(q.substr(1)); // print address of temporary
is conceptually equivalent to: 在概念上等同于:
std::string q("abcd");
{
const std::string& lref = q.substr(1);
std::cout << &lref << std::endl;
}
where the temporary experiences a prolongation of its lifetime to the end of the scope in which lref
is defined (which is to the end of PrintAddress
function scope in the present example). 其中所述临时经历其寿命,其中所述范围的端部的延长
lref
被定义(其是在2002年底PrintAddress
功能范围在本例中)。
what does the address represent?
地址代表什么? What lives there?
那里住着什么?
A std::string
object containing the passed content. 包含传递内容的
std::string
对象。
And is it legal (in C++, and with respect to memory) to write to that address?
写入该地址是合法的(在C ++中,在内存方面)?
No, it would be legal if you'd use an rvalue reference: 不,如果您使用右值参考,那将是合法的:
void PrintAddressR(std::string&& rref) {
rref += "Hello"; // writing possible
std::cout << &rref << std::endl; // taking the address possible
}
// ...
PrintAddressR(q.substr(1)); // yep, can do that...
The same applies here: rref
is an lvalue (it has a name) so you can take its address plus it is mutable. 这同样适用于:
rref
是一个左值(它有一个名字)所以你可以拿它的地址加上它是可变的。
In short, because the prvalue's lifetime has been extended. 简而言之,因为prvalue的寿命已经延长。 By having its lifetime extended - by any reference -, it's an lvalue, and thus can have its address taken.
通过延长寿命 - 通过任何引用 - 它是一个左值,因此可以得到它的地址。
what does the address represent?
地址代表什么? What lives there?
那里住着什么?
The address represents an object, the object referenced by lref
. 地址表示一个对象,即
lref
引用的对象。
A prvalue is short lived, it doesn't live for long. prvalue是短暂的,它不会长寿。 In fact, it will be destroyed when the statement creating it ends.
实际上,当创建它的语句结束时,它将被销毁。
But, when you create a reference to a prvalue (either an rvalue reference or a const lvalue reference), its lifetime is extended. 但是,当您创建对prvalue(rvalue引用或const lvalue引用)的引用时,它的生命周期会延长。 Ref.: :
参考 :
An rvalue may be used to initialize a const lvalue [ rvalue ] reference, in which case the lifetime of the object identified by the rvalue is extended until the scope of the reference ends .
rvalue可用于初始化const lvalue [ rvalue ]引用,在这种情况下,由rvalue标识的对象的生命周期将延长,直到引用的范围结束 。
Now it makes actually sense to take its address, as it is an lvalue for all intents and purposes. 现在获取其地址实际上是合理的,因为它是所有意图和目的的左值。 Now, that the prvalue has an indeterminate lifetime, it is an lvalue.
现在,prvalue具有不确定的生命周期,它是一个左值。
Taking the address of a prvalue doesn't make sense however, and that's probably why it is disallowed: 然而,取一个prvalue的地址是没有意义的,这可能是它被禁止的原因:
If you take the address of something, the compiler is required to actually create the object. 如果你取一些东西的地址,编译器需要实际创建对象。 Sometimes, the compiler will optimize out variables that are trivial, but if you were to take the address of them, the compiler won't be allowed to optimize them out.
有时,编译器会优化掉微不足道的变量,但是如果要获取它们的地址,则不允许编译器优化它们。
Taking the address of a prvalue will thus result in the compiler being unable to elide the value completely, for no advantages whatsoever (see point 1). 因此,获取prvalue的地址将导致编译器无法完全忽略该值,因为没有任何优点(参见第1点)。
In simple English: 用简单的英语:
void PrintAddress(const std::string& lref) {
std::cout << &lref << std::endl;
}
Any object that has a name is an lvalue
, hence any use of lref
within the scope of the funtion above is an lvalue
use. 任何具有名称的对象都是
lvalue
,因此在上述功能范围内使用lref
是lvalue
使用。
When you called the function with: 用以下方法调用函数时:
PrintAddress(lref.substr() /* temporary of type std::string */)
Of cause, lref.substr()
produces a temporary which is an rvalue
, but rvalues
can bind to (have its lifetime extended by) const lvalue references or rvalue references. 原因是,
lref.substr()
生成一个临时rvalue
,它是一个rvalue
,但是rvalues
可以绑定(使其生命周期延长)const lvalue引用或rvalue引用。
Even if you provided an rvalue
overload, for the fact it has a name , its an "lvalue of something" within its scope, example: 即使你提供了一个
rvalue
重载, 因为它有一个名字 ,它的范围内有一个“lvalue of something” ,例如:
#include <string>
#include <iostream>
void PrintAddress(const std::string& lref) {
std::cout << "LValue: " << &lref << std::endl;
}
void PrintAddress(std::string&& `rref`) {
std::cout << "RValue: " << &rref << std::endl; //You can take address of `rref`
}
int main(){
std::string str = "Hahaha";
PrintAddress(str);
PrintAddress(str.substr(2));
}
Just remember: 只记得:
In C++, any object(whether value type , reference type or pointer type ) that has a name is an lvalue
在C ++中, 任何物体(是否值类型 , 引用类型或指针类型 ),其具有一个名字是一个左值
Also know that some expressions produce lvalues too. 也知道一些表达式也产生左值 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.