C++中的左值和右值
2016-04-20 14:54
369 查看
左值和右值的定义
从C中继承而来左值:既能出现在等号左边也能出现在等号右边的变量(或表达式)。通常来说,有名字的变量即左值,且左值是在程序中能够寻址的东西。
右值:只能出现在等号右边的变量(或表达式)。由运算操作(加减乘除,函数调用返回值等)所产生的的中间结果(没有名字)即右值,右值是没法取得它的地址的。
在C++中的不同
对于内置的类型: 左值和右值的概念和C区别不大,右值是不可被修改的,也不可被const,volatile所修饰。
对于自定义的类型: 右值却允许通过它的成员函数进行修改,且能被const类型的引用所指向
左值引用,右值引用
举例代码:class cs { public: cs(int i): i_(i) { cout << "cs(" << i <<") constructor!" << endl; } ~cs() { cout << "cs destructor,i(" << i_ << ")" << endl; } cs& operator=(const cs& other) { i_ = other.i_; cout << "cs operator=()" << endl; return *this; } int get_i() const { return i_; } void change(int i) { i_ = i; } private: int i_; }; cs get_cs() { static int i = 0; return cs(i++); } int main() { // 合法 (get_cs() = cs(2)).change(323); get_cs() = cs(2);// operator=() get_cs().change(32); return 0; }
P.s.1 : 右值能被const类型的引用所指向
合法写法:
const cs& ref = get_cs();
Error:
cs& ref = get_cs();
即:当一个右值被const指向时,其生命周期就被延长(右值不能被当成左值使用,但左值能被当成右值使用)
P.s.2 : 非 const reference 不能引用 rvalue
void func(cs& c) { cout << "c:" << c.get_i() << endl; } //合法: func(get_cs() = get_cs() ); //error func(get_cs());
P.s.3 : 不同的拷贝复制函数
class cs { public: cs& operator=(const cs& c); }; // 另一种写法 class cs2 { public: cs2& operator=(cs2& c); };
上面两种写法的不同之处就在于参数,一个是 const reference,一个是非 const。对于自定义类型的参数,通常来说,如果函数不需要修改传进来的参数,我们往往就按 const reference 的写法。
P.s.4 : 需要修改参数的值
// 类似auto_ptr class auto_ptr { public: auto_ptr(auto_tr& p) { ptr_ = p.ptr_; p.ptr_ = NULL; } private: void* ptr_; };
所以,对于 auto_ptr 来说,它的 copy constructor 的参数类型是 non const reference。有些情况下,这种写法应该被鼓励,毕竟 non const reference 比 const reference 更能灵活应对各种情况,从而保持一致的接口类型,当然也有代价,参数的语义表达不准确了。除此更大的问题是如果拷贝构造函数写成这样子,却又对 rvalue 的使用带来了极大的不变,如前面所讲的例子,rvalue 不能被 non const reference 所引用,所以像 auto_ptr 的这样的类的 copy constructor 就不能接受 rvalue.
举个栗子:
//错误 auto_ptr p(get_ptr()); //operator=() 同理,错误 auto_ptr p = get_ptr();
这也是 auto_ptr 很不好用的原因之一,为了解决这个问题,c++11 中引入了一种新的引用类型,该种引用是专门用来指向 rvalue 的,有了这种新类型,对 lvalue 和 rvalue 的引用就能明确区分开来了。因为有了这种新的类型,接着就引出了 c++11 中新的语义,move(), forward() 等.
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C与C++之间相互调用实例方法讲解
- 解析C++中派生的概念以及派生类成员的访问属性