&与&&
对于在C++中,大家对于符号“ & ”的第一映像是引用和取地址,对符号“ && ”的第一映像是逻辑与。但是在C++11中我们会看到下方这种表示方法:
int &&k=i+k;
1
对于第一眼见到上述的表达方式时,估计会一脸懵逼。下面对此做一个简述。
引用 & 是一个类型变量的别名。
通常使用 “ & ”是作为普通的左值引用,左值是可以放在赋值号 “ = ”的左边的值。
&&是右值引用,右值是只能放在 “ = ” 右边的值,右值没有一个 “ 变量 ”名字。如:
int && k =i+j;
1
i+j 返回的值可以视做是放在一个临时存放内存空间里的,这个空间并不能用来赋值,你不能些i+j=5等; && 可以把这种临时的值和存在变量里的值区分开来。
右值短暂,右值只能绑定到临时对象。所引用的对象将要销毁或对象没有其他用户。
初始化时右值引用一定要用一个右值表达式绑定,初始化之后,可以用左值表达式或修改右值引用的所引用临时对象的值。
右值引用是对临时对象的一种引用,它是在初始化时完成引用的,但是右值引用不代表引用临时对象后,就不能改变右值引用所引用对象的值。仍然可以在初始化后改变临时对象的值。
对于引用类型,可以用于它所引用对象类型的可以用的地方(把他当成普通变量),只不过用到的值是它所引用的对象的值,还可以用于移动构造和赋值函数的地方。
例子
#include <algorithm>
#include <iostream>
#include <functional>
#include <vector>
#include <numeric>
#include <array>
#include <cstring>
#include <cstdio>
#include <windows.h>
using namespace std;
//c++能用引用的情况就不要用指针
int main1()
{
int num = 10;//num左值,内存实体
int& rnum(num);//变量的别名
rnum = 1;//rnuum等价于num的别名
cout << num << endl;//1
system("pause");
}
右值引用 ,节约内存,快速引用寄存器的值
int main()
{
int num = 1;
int &&rnum(num + 4);//右值引用,快速备份,编译器自动回收
printf("%p",&rnum);
int data = num+4;
int &rdata(data);//左值引用
cout << (void*)&data << endl;
data=num+1;
}
void main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *p(a);
//cout << *p << endl;//1
//int* &rp(p);//左值引用改变指针
//rp += 1;
//cout << *p << endl;//2
int *&&rrp(p+2);//右值引用&&
cout << *rrp << endl;//3
rrp += 2;
cout << *rrp << endl;//5
}
void showit(int&& rrnum)
{
cout << rrnum << endl;
}
//左值应用往往引用的是内存里面的值,而右值引用一般是寄存器里面的值
void main()
{
int a[5] = { 1, 2, 3, 4, 5 };
showit(a[3] + 2);//5,右值引用大大节约内存
showit(move(a[3]));//move移动语义,左值变长右值
}
引用的本质:
#include <algorithm>
#include <iostream>
#include <functional>
#include <vector>
#include <numeric>
#include <array>
#include <cstring>
#include <cstdio>
#include <windows.h>
using namespace std;
void main1()
{
int num = 10;
int data = 20;
int & rnum(num);//引用一旦初始化,不会再引用其他的变量
rnum = data;
cout << num << endl;//20
cout << data << endl;20
}
void main()
{
double db;
double&rdb(db);
cout << sizeof(rdb) << endl;//8,编译器优化处理,引用变量名的别名
struct Mystruct //引用的本质是指针实现的,用于简化程序
{
double &rdb;
};
cout << sizeof(Mystruct) << endl;//4
}
引用作为参数
#include <algorithm>
#include <iostream>
#include <functional>
#include <vector>
#include <numeric>
#include <array>
#include <cstring>
#include <cstdio>
#include <windows.h>
using namespace std;
//改变指针需要二级指针
//栈区,自动回收,释放,返回值为指针,不能指向栈区,返回引用,不能引用栈区
int main()
{
int a(4);//初始化为4
int*p(new int(5));//初始化为5
cout << a << endl;//4
cout << *p << endl;//5
int &ra(a);//引用变量
int*&rp(p);//引用指针
ra = 3;
*rp = 12;
cout << a << endl;//3
cout << *p << endl;//12
cin.get();
}
int main()
{
int a(4);//初始化为4
int*p(new int(5));//初始化为5
cout << a << endl;//4
cout << *p << endl;//5
int&&rra(move((a)));//右值,有内存实体,就直接引用,没有就开辟内存
int *&&rrp(move(p));
rra = 1;
cout << rra <<endl;//1
cout << a << endl;//1
//int&:引用内存实体,引用整数,本质是指针
//int&&:引用整数,本质是指针,能处理左值和右值,处理左值需要配合move
//int:整数类型
cin.get();
}
int num1 = 10;
int num2 = 20;
void change(int *&rp)
{
rp = &num2;
}
void main()//c++能用引用就别用指针
{
int *p = #
change(p);
cout << *p << endl;//20;
}
int main()
{
int *p(nullptr);
int**pp = &p;
int**&rpp = pp;//vs2015
//vs2013中:int(**(&rpp))(pp);
//vs2013:int(*(&rpf)),需考虑优先级
}
void main()
{
//vs2015
int***ppp(nullptr);
int***&rppp(ppp);
//vs2013
int(***ppp)(nullptr);
int(***(&rppp))(ppp);
}
int data = 10;
int data2 = 20;
int *p = &data;
void change(int **&rpp)//引用
{
*rpp = &data2;
}
int main()
{
int **pp = &p;//二级指针
cout << **pp << endl;//10;
change(pp);
cout << **pp << endl;//20;
}
int& getdata()
{
int num = 10;//销毁了,调用结束自动销毁
return num;
}
int main()
{
//int & rnum = getdata();//引用原来的内存,已经销毁的地方,乱码
int & rnum = getdata();//拷贝到新的内存
cout << "hello";
cout << rnum << endl;
printf("%d",getdata());//10
}
char*& getcode()
{
char*p = "hello world";//指向只读数据区
return p;
}
void main()
{
char*&rp = getcode();//引用本质是指针,引用的就是函数中的p,而那个内存可能已经释放
char*newp = rp;//保存rp存储代码区的地址
cout << "hello " << endl;
cout << newp << endl;//输出hello world
cout << rp << endl;//乱码;
}
引用一个数组及引用数组是非法的
#include <algorithm>
#include <iostream>
#include <functional>
#include <vector>
#include <numeric>
#include <array>
#include <cstring>
#include <cstdio>
#include <windows.h>
using namespace std;
int main()
{
int a[5]{1, 2, 3, 4, 5};
int *pa[5] = { a, a + 1, a + 2, a + 3, a + 4 };
int b[3][4]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
int*pb[3][4]{&b[0][0], &b[0][0] + 1, &b[0][0] + 2, &b[0][0]+3,........}
int *p1(new int[5]{1, 2, 3, 4, 5});//堆上的一维数组
int(*p2)[4](new int[3][4]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12});//堆上的二维数值
cin.get();
}
void main()
{
int a[5]{1, 2, 3, 4, 5};
//int a[5] == == > int(&ra)[5](a);//引用数组,用a初始化
int *pa[5] = { a, a + 1, a + 2, a + 3, a + 4 };
int(&ra)[5](a);//引用数值
int*(&rpa)[5](pa);//引用指针数值
for(auto& i:ra)
{
cout << i+=1 << endl;//会修改数据
}
for (auto i:rpa)
{
cout << *i << endl;
}
}
void main()
{
// int *p1(new int[5]{1, 2, 3, 4, 5});//堆上的一维数组
// int **pp ( new int*[5]{p1,p1+1,p1+2,p1+3,p1+4});//堆上的指针数组
// int*&rp(p1);
// int **&rpp(pp);//vs2015
//vs2013以下
int *p1(new int[5]{1, 2, 3, 4, 5});//堆上的一维数组
int *(*pp) ( new int*[5]{p1,p1+1,p1+2,p1+3,p1+4});//堆上的指针数组
int(*(&rp))(p1);
int (**(&rpp))(pp);
for (int i = 0; i < 5;i++)
{
cout << rp[i] << endl;
}
for (int i = 0; i < 5; i++)
{
cout << *rpp[i] << endl;
}
}
void main()
{
int b[3][4]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
int*pb[3][4]{&b[0][0], &b[0][0] + 1, &b[0][0] + 2, &b[0][0] + 3, ........}
int(&rb)[3][4](b);//引用二维数值
int *(&rpb)[3][4](pb);
for (int i=0;i<3;i++)
{
for (int j = 0; j < 4; j++)
{
cout << rb[i][j];
}
}
for (int i = 0;i < 3;i++)
{
for (int j = 0; j < 4; j++)
{
cout << *rpp[i][j];
}
}
}
void main()
{
//指向数组的指针,{}包含
int(*p2)[4](new int[3][4] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } });//堆上的二维数值
int(*&rp)[4](p);
int*(*pp)[4](new int*[3][4]);//在堆上开辟二维指针数值
int*(*&rpp)[4](pp);//引用二维指针数组
for (int i = 0;i < 3;i++)
{
for (int j = 0; j < 4; j++)
{
cout << rp[i][j];
}
}
}
int main)
{
int a = 1;
int &ra(a);
int b = 2;
int &rb(b);
int c = 3;
int &rc(c);
int &myarr[3]{ra, rb, rc};//错误,引用数组非法,只能单独引用
}
加const的引用
#include <algorithm> #include <iostream> #include <functional> #include <vector> #include <numeric> #include <array> #include <cstring> #include <cstdio> #include <windows.h> using namespace std; void main1() { int num = 100; int const& rnum(num);//让别人引用,限定权限,只能读不能写 //rnum =3//不允许对常量赋值 cout << rnum << endl; } void main2() { int num = 100; //int & const rnum(num);// 使用了记时错误: 忽略引用上的限定符,const会被忽略 } void main3() { int a[5] = { 1, 2, 3, 4, 5 }; const int(&ra)[5](a); for (auto &i:ra) { //i+=1;//只能读,不能写 cout << i << endl;//只能读,不能写 } cin.get(); } void main() { int *p(new int(5)); //int *&rp(p); int (*(&rp))(p);// *rp = 3; cout << *p << endl;//3 } void main() { const int *const p(new int(4)); *p = 1; const int*(*const(&rp))(p);//引用一个常量的常量指针 } void show( const int& p)//明确只读 void main() { int *p(new int(4)); const int *&rp((const int *&)p);//强转成const int *的引用 }