c++------引用(左值与右值,引用一个数组,const限制)
&与&&
对于在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 *的引用 }