当函数参数类型为lvalue引用lref时
void PrintAddress(const std::string& lref) {
std::cout << &lref << std::endl;
}lref被绑定到一个prvalue:
PrintAddress(lref.substr() /* temporary of type std::string */)地址代表什么?那里住的是什么?
不能取它的地址。但是,对prvalue的lvalue引用可以获取它的地址,这对我来说很奇怪。
发布于 2017-03-12 20:23:49
简而言之,因为prvalue的生存期已经延长了。通过延长它的生存期-通过任何引用-,它是一个lvalue,因此它的地址可以被取走。
地址代表什么?那里住的是什么?
该地址表示一个对象,即lref引用的对象。
价值是短暂的,它活不了多久。事实上,当创建它的语句结束时,它将被销毁。
但是,当您创建对prvalue ( rvalue引用或const值引用)的引用时,它的生存期将被延长。参考文献:
rvalue可用于初始化const rvalue引用,在这种情况下,由rvalue标识的对象的生存期被延长,直到引用的范围结束为止。
现在,获取它的地址实际上是有意义的,因为它对于所有意图和目的都是一个值。现在,prvalue具有不确定的生存期,因此它是一个lvalue。
然而,获取prvalue的地址是没有意义的,这可能就是不允许使用prvalue的原因:
发布于 2017-03-12 20:11:58
在函数内部,lref不是prvalue,而是lvalue,您可以获取它的地址。
对于rvalue和lvalue,有一种常见的误解。命名参数始终是一个lvalue。不管它是否是绑定到rvalue的引用类型。通过const &引用类型,您甚至无法判断对象在调用函数时实际拥有哪种类型的值类别。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...
}临时字符串是调用方上下文中的一个prvalue (在调用PrintAddress时)。在被调用的上下文中(在PrintAddress中),lref是一个lvalue引用,因为在这个上下文中,它实际上是一个lvalue。
PrintAddress不知道传递的参数的生存期有限,从PrintAddress的角度来看,对象是“始终存在”的。
std::string q("abcd");
PrintAddress(q.substr(1)); // print address of temporary在概念上相当于:
std::string q("abcd");
{
const std::string& lref = q.substr(1);
std::cout << &lref << std::endl;
}其中,临时的生命周期延长到定义lref的作用域的末尾(在本例中,这是PrintAddress函数作用域的结束)。
地址代表什么?那里住的是什么?
包含传递内容的std::string对象。
写到这个地址(在C++中,以及在内存方面)合法吗?
不,如果您使用rvalue引用是合法的:
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...同样适用于这里:rref是一个lvalue (它有一个名称),所以您可以获取它的地址,加上它是可变的。
发布于 2017-03-12 20:16:41
用简单的英语:
void PrintAddress(const std::string& lref) {
std::cout << &lref << std::endl;
}任何具有名称的对象都是lvalue,因此在上述函数范围内对lref的任何使用都是lvalue使用。
当您用以下方法调用函数时:
PrintAddress(lref.substr() /* temporary of type std::string */)当然,lref.substr()生成一个临时的rvalue,但是rvalues可以绑定到const引用或rvalue引用(使其生命期延长)。
即使您提供了一个rvalue重载,但实际上它有一个名称,它是其范围内的“某个东西的值”,例如:
#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));
}记住:
在C++中,任何具有名称的对象(无论是值类型、引用类型还是指针类型)都是lvalue。
也要知道一些表达也会产生lvalue。
https://stackoverflow.com/questions/42752455
复制相似问题