返回信息流1、什么是左值/右值?
2、什么是左值引用/右值引用?
3、左值和左值引用,右值和右值引用有关系吗?
```C
struct A {
};
void f(A& a) {
cout << "invoke void f(A& a) " << endl;
}
void f(A&& a) {
cout << "invoke void f(A&& a) " << endl;
}
template<typename T>
void g(T&& t) {
}
int main() {
A a;
A& a_left_reference = a;
A&& a_right_reference = A();
f(a);
f(a_left_reference);
f(a_right_reference);
f((A)a);
f((A&)a);
f((A&&)a);
system("pause");
}
```
输出结果为:
invoke void f(A& a)
invoke void f(A& a)
invoke void f(A& a)
invoke void f(A&& a)
invoke void f(A& a)
invoke void f(A&& a)
这是一条镜像帖。来源:北邮人论坛 / cpp / #95109同步于 2017/4/15
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
【问题】左值/右值 与 左值引用/右值引用
liuyehcf
2017/4/15镜像同步8 回复
订阅后,新回复会通过你的通知中心匿名送达。
8 条回复
什么是左值/右值这个问题应该随便找本 C++ 教材都有吧,楼主请找一本来读一读。
后面几个问题请读一读 Effective Modern C++
和
http://thbecker.net/articles/rvalue_references/section_01.html
http://eli.thegreenplace.net/2014/perfect-forwarding-and-universal-references-in-c/
http://en.cppreference.com/w/cpp/language/value_category
disclaimer:我不懂 C++,我只是给人甩链接。不要追问我……
谢谢~看了链接,讲的挺好的~
【 在 Vampire 的大作中提到: 】
: 什么是左值/右值这个问题应该随便找本 C++ 教材都有吧,楼主请找一本来读一读。
:
: 后面几个问题请读一读 Effective Modern C++
:
: 和
: http://thbeck
: .........
发自「贵邮」
嗯,我查过一些。从我第一次接触这个两个概念到现在,这个困惑从未消除过
以下是我的理解
1、我觉得左右值属性和左右值引用是完全独立的两个东西,左右值是表达式的属性,而左右值引用是类型信息
2、我觉得函数在进行重载版本选择时,依据的是左右值属性而与左右引用无关,例如例子中的f(a);f(al);f(ar);都会调用左值引用的版本,因为变量本身都是左值
3、让我感到奇怪的是,例子中后三个调用
```C
f((A)a);//右值引用版本
f((A&)a);//左值引用版本
f((A&&)a);//右值引用版本
```
a原本是一个左值,(A)a却变成了一个右值?我仅仅做了个转型而已啊
另外还有一个问题是,T&&配合std::forward可以实现完美转发,但是右值引用好像不能保留实参所有信息,例如下面这个
```C
template<typename T>
void h(T&& t) {
}
int main() {
int &&i = 5;
h(i);//模板实参推断T=int&
}
```
我理解实参i的所有信息包括
1、i的类型信息:非const;int类型;右值引用
2、i的左右值属性:左值
但是这个T&&并没有保留i的右值引用这个属性
【 在 nuanyangyang 的大作中提到: 】
: 你问搜索引擎了吗?
:
右值引用主要是用来引用那些“快要死了的值”(xvalue,是rvalue的一种)。所以int &&i = 6;这种没什么意义。但如果用于引用某个函数返回的对象,就很有用了,可以趁这个对象没死,把它里面的重要资源(比如文件描述符,或者分配的内存)抢救出来。
没错,就是转换一下,就能选择究竟是使用左值引用的版本还是使用右值引用的版本。一般来说,这样重载的两个函数语义完全不同,只是名字碰巧一样而已。比如:
basic_string& operator=( const basic_string& str );
basic_string& operator=( basic_string&& str );
第一个是拷贝参数str里的内容,第二个是直接把str里的内容抢过来。它们是语义不同的两个函数,只是名字一样。所以,编译器看到“a=b“这样的表达式,就只能通过b的类型来判断使用哪个函数了。
【 在 liuyehcf 的大作中提到: 】
: 嗯,我查过一些。从我第一次接触这个两个概念到现在,这个困惑从未消除过
: 以下是我的理解
: 1、我觉得左右值属性和左右值引用是完全独立的两个东西,左右值是表达式的属性,而左右值引用是类型信息
: ...................
另外,如果这么喜欢move语义,要不要学学rust语言?所有自定义类型默认都是move语义赋值,除非显式clone或者实现Copy trait
谢暖神
我大概明白你的意思了,我是不是可以这么理解
1、右值引用主要是用于引用那些快死了的值,比如直接绑定到函数返回的临时对象上(并没有移动语义,只是延长了这个临时对象的生命周期,直到这个右值引用变量生命周期结束);如果是拷贝的话,一旦拷贝完成,临时对象就被销毁了
2、而std::move配合移动构造函数或者移动赋值运算符主要用于窃取资源,即移动语义
【 在 nuanyangyang 的大作中提到: 】
: 右值引用主要是用来引用那些“快要死了的值”(xvalue,是rvalue的一种)。所以int &&i = 6;这种没什么意义。但如果用于引用某个函数返回的对象,就很有用了,可以趁这个对象没死,把它里面的重要资源(比如文件描述符,或者分配的内存)抢救出来。
: 没错,就是转换一下,就能选择究竟是使用左值引用的版本还是使用右值引用的版本。一般来说,这样重载的两个函数语义完全不同,只是名字碰巧一样而已。比如:
: [code=c]
: ...................
差不多
【 在 liuyehcf 的大作中提到: 】
: 谢暖神
: 我大概明白你的意思了,我是不是可以这么理解
: 1、右值引用主要是用于引用那些快死了的值,比如直接绑定到函数返回的临时对象上(并没有移动语义,只是延长了这个临时对象的生命周期,直到这个右值引用变量生命周期结束);如果是拷贝的话,一旦拷贝完成,临时对象就被销毁了
: ...................