C++ 左值引用和右值引用(C++11特性)
2016-04-30 18:34
676 查看
前言
引用就是别名(alias)。所谓别名,就是对已存在的对象另起一个名字。本身含义并不难理解,但与其它概念一组合,就成了使用难点。再加上新标准提出了新的一种引用-右值引用,引用这一概念就变得更加难以理解和使用。
正文
随着新标准(新标准往往就是新的技术)的提出,引用这一概念分成两类:左值引用、右值引用。其中左值引用是最常用的一种,而右值引用则是语言使用上的一种革新。
1.左值引用
左值引用的基本语法
Type &引用名 = 左值表达式;
#include <iostream>
using namespace std;
int main()
{
int a = 10;
//ra是a的引用(别名),相当于把ra与a绑定。
int &ra(a);
cout << ra << " " << (void*)&ra << " " << (void*)&a << endl;
cin.get();
return 0;
}
运行
10 0110F978 0110F978
11
引用的基本规则
1.声明引用的时候必须初始化,且一旦绑定,不可把引用绑定到其他对象。
2.对引用的一切操作,就相当于对原对象的操作。
2.右值引用
以上是最常见的引用方式,我们称之为左值引用。为了顺利区分左右值引用的概念,我们先来看下左右值的概念。
首先,左右值是表达式的属性。何为表达式?表达式由一个或多个运算对象组成。字面值和变量是最简单的表达式。
一个对象被用作右值时,使用的是它的内容(值),被当作左值时,使用的是它的地址。
int a = 1;
a + 1; //a + 1 是表达式
在C++旧标准中,我们可以引用a,但却无法引用a+1,这是为什么呢?
这是因为,变量a被创建后,在它的作用域内是一直存在的。如此一来,它的引用是有存在意义的。而a+1不是一个对象,在运算中临时存在于寄存器中,而寄存器中的值是时刻被刷新的,创建a+1的引用显得没有任何意义。为了成功的使用类似于a+1这种右值的引用。C++新标准提出了区别于以往的引用-右值引用。
右值引用的基本语法
Type &&引用名 = 右值表达式;
#include <iostream>
using namespace std;
int main()
{
int a = 10;
//右值引用
int &&ra(a+1);
cout << ra << ends << (void*)&ra << ends << (void*)&a << endl;
ra++;
cout << ra << endl;
cin.get();
return 0;
}
运行结果:
11 0110F978 0110F978
12
**看几个例子
int i = 42;
int &r = i; // lvalue reference
int &&rr = i; // rvalue reference (Error: i is a lvalue)
int &r2 = i*42;
// lvalue reference (Error: i*42 is a rvalue)
const int &r3 = i*42;
// reference to const (bind to a rvalue)
int &&rr2 = i*42;
// rvalue reference
对右值引用的一种可能的内部实现解释
int a = 1;
int *p = new int(a + 1);
int &ra = *p;
delete p; //不再使用引用了,动态内存的释放由C++自动管理
其中第二、三两句就对应右值引用:int &&ra(a+1);
3.引用作为函数参数
引用作为函数参数时,有着指针一样的功能。
#include <iostream>
using namespace std;
void fun(int &ra)
{
cout << ra << ends << (void*)&ra << endl;
ra++;
}
int main()
{
int a = 10;
fun(a);
cout << a << ends << (void*)&a << endl;
cin.get();
return 0;
}
运行
10 0115FB14
11 0115FB14
在函数fun内,对形参ra的值,做出了更改,这一操作影响了实参a。显然引用的使用比指针简单。
4.引用与数组
int a[]{1, 2, 3, 4, 5};
int (&ra)[5] = a; //对数组进行引用
5.引用与指针
引用一级指针
int a(0), *p = &a;
int *&rp = p;
引用二级指针
int a(0), *p = &a;
int **pp = &p;
int **&rp = pp; //引用二级指针,若编译不通过,使用 int (**(&rp)) = pp;
6.引用与函数指针
#include <iostream>
using namespace std;
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int divi(int a, int b)
{
if (b)
return a / b;
else
return INFINITY;
}
int main()
{
int a(100), b(10);
cout << "使用函数名" << endl;
cout << add(a, b) << ends << sub(a, b) << ends << mul(a, b) << ends << divi(a, b) << endl;
//padd是函数指针
int(*pfun)(int, int);
cout << "使用函数指针" << endl;
pfun = add;
cout << pfun(a, b) << ends;
pfun = sub;
cout << pfun(a, b) << ends;
pfun = mul;
cout << pfun(a, b) << ends;
pfun = divi;
cout << pfun(a, b) << endl;
//函数指针数组
int(*pfuns[])(int, int){add, sub, mul, divi};
cout << "使用函数指针数组" << endl;
cout << pfuns[0](a, b) << ends << pfuns[1](a, b) << ends << pfuns[2](a, b) << ends << pfuns[3](a, b) << endl;
cout << "函数指针的引用" << endl;
int(*(&rfun0))(int, int)(pfuns[0]);
int(*(&rfun1))(int, int)(pfuns[1]);
int(*(&rfun2))(int, int)(pfuns[2]);
int(*(&rfun3))(int, int)(pfuns[3]);
cout << rfun0(a, b) << ends << rfun1(a, b) << ends << rfun2(a, b) << ends << rfun3(a, b) << endl;
cin.get();
return 0;
}
自己可以试试,很简单。
本篇文章来源于 Linux公社网站(www.linuxidc.com) 原文链接:http://www.linuxidc.com/Linux/2015-02/114056.htm
引用就是别名(alias)。所谓别名,就是对已存在的对象另起一个名字。本身含义并不难理解,但与其它概念一组合,就成了使用难点。再加上新标准提出了新的一种引用-右值引用,引用这一概念就变得更加难以理解和使用。
正文
随着新标准(新标准往往就是新的技术)的提出,引用这一概念分成两类:左值引用、右值引用。其中左值引用是最常用的一种,而右值引用则是语言使用上的一种革新。
1.左值引用
左值引用的基本语法
Type &引用名 = 左值表达式;
#include <iostream>
using namespace std;
int main()
{
int a = 10;
//ra是a的引用(别名),相当于把ra与a绑定。
int &ra(a);
cout << ra << " " << (void*)&ra << " " << (void*)&a << endl;
cin.get();
return 0;
}
运行
10 0110F978 0110F978
11
引用的基本规则
1.声明引用的时候必须初始化,且一旦绑定,不可把引用绑定到其他对象。
2.对引用的一切操作,就相当于对原对象的操作。
2.右值引用
以上是最常见的引用方式,我们称之为左值引用。为了顺利区分左右值引用的概念,我们先来看下左右值的概念。
首先,左右值是表达式的属性。何为表达式?表达式由一个或多个运算对象组成。字面值和变量是最简单的表达式。
一个对象被用作右值时,使用的是它的内容(值),被当作左值时,使用的是它的地址。
int a = 1;
a + 1; //a + 1 是表达式
在C++旧标准中,我们可以引用a,但却无法引用a+1,这是为什么呢?
这是因为,变量a被创建后,在它的作用域内是一直存在的。如此一来,它的引用是有存在意义的。而a+1不是一个对象,在运算中临时存在于寄存器中,而寄存器中的值是时刻被刷新的,创建a+1的引用显得没有任何意义。为了成功的使用类似于a+1这种右值的引用。C++新标准提出了区别于以往的引用-右值引用。
右值引用的基本语法
Type &&引用名 = 右值表达式;
#include <iostream>
using namespace std;
int main()
{
int a = 10;
//右值引用
int &&ra(a+1);
cout << ra << ends << (void*)&ra << ends << (void*)&a << endl;
ra++;
cout << ra << endl;
cin.get();
return 0;
}
运行结果:
11 0110F978 0110F978
12
**看几个例子
int i = 42;
int &r = i; // lvalue reference
int &&rr = i; // rvalue reference (Error: i is a lvalue)
int &r2 = i*42;
// lvalue reference (Error: i*42 is a rvalue)
const int &r3 = i*42;
// reference to const (bind to a rvalue)
int &&rr2 = i*42;
// rvalue reference
对右值引用的一种可能的内部实现解释
int a = 1;
int *p = new int(a + 1);
int &ra = *p;
delete p; //不再使用引用了,动态内存的释放由C++自动管理
其中第二、三两句就对应右值引用:int &&ra(a+1);
3.引用作为函数参数
引用作为函数参数时,有着指针一样的功能。
#include <iostream>
using namespace std;
void fun(int &ra)
{
cout << ra << ends << (void*)&ra << endl;
ra++;
}
int main()
{
int a = 10;
fun(a);
cout << a << ends << (void*)&a << endl;
cin.get();
return 0;
}
运行
10 0115FB14
11 0115FB14
在函数fun内,对形参ra的值,做出了更改,这一操作影响了实参a。显然引用的使用比指针简单。
4.引用与数组
int a[]{1, 2, 3, 4, 5};
int (&ra)[5] = a; //对数组进行引用
5.引用与指针
引用一级指针
int a(0), *p = &a;
int *&rp = p;
引用二级指针
int a(0), *p = &a;
int **pp = &p;
int **&rp = pp; //引用二级指针,若编译不通过,使用 int (**(&rp)) = pp;
6.引用与函数指针
#include <iostream>
using namespace std;
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int divi(int a, int b)
{
if (b)
return a / b;
else
return INFINITY;
}
int main()
{
int a(100), b(10);
cout << "使用函数名" << endl;
cout << add(a, b) << ends << sub(a, b) << ends << mul(a, b) << ends << divi(a, b) << endl;
//padd是函数指针
int(*pfun)(int, int);
cout << "使用函数指针" << endl;
pfun = add;
cout << pfun(a, b) << ends;
pfun = sub;
cout << pfun(a, b) << ends;
pfun = mul;
cout << pfun(a, b) << ends;
pfun = divi;
cout << pfun(a, b) << endl;
//函数指针数组
int(*pfuns[])(int, int){add, sub, mul, divi};
cout << "使用函数指针数组" << endl;
cout << pfuns[0](a, b) << ends << pfuns[1](a, b) << ends << pfuns[2](a, b) << ends << pfuns[3](a, b) << endl;
cout << "函数指针的引用" << endl;
int(*(&rfun0))(int, int)(pfuns[0]);
int(*(&rfun1))(int, int)(pfuns[1]);
int(*(&rfun2))(int, int)(pfuns[2]);
int(*(&rfun3))(int, int)(pfuns[3]);
cout << rfun0(a, b) << ends << rfun1(a, b) << ends << rfun2(a, b) << ends << rfun3(a, b) << endl;
cin.get();
return 0;
}
自己可以试试,很简单。
本篇文章来源于 Linux公社网站(www.linuxidc.com) 原文链接:http://www.linuxidc.com/Linux/2015-02/114056.htm
相关文章推荐
- C语言之内存字节对齐
- 练习题c++(一)
- C++中istream的使用
- C++中istream的使用
- C语言错误: HEAP CORRUPTION DETECTED
- C++读取Excel 精华
- C++ 访问控制(public,protected,private)
- 【c++】istream 转为 string
- C++学习笔记60——模板编译模型
- c#调用c++制作的基于mfc的ocx控件
- 基本单链表的增删改C++
- 数组&字符串&结构体&共用体&枚举
- c语言中的段和内存四区
- C++定义一个对象和new一个对象的区别与联系
- 【C++ STL系列】迭代器 iterator
- 《More Effective C++》读书笔记-操作符
- 通过表达式构造二叉树 c++
- C++中的istringstream、ostringstream、stringstream
- C++单例的创建与使用
- c语言中的位移位操作