0x01:簡單的引用
c語言中沒有引用,c++有引用,簡化編程
引用的本質就是指針,給已經存在的變量起一個別名,sizeof求大小訪問的是引用的變量
引用必須一開始就初始化,一旦初始化,賦值修改將無效;
int num = 10;
int & rnum (num);//變量引用用括號好初始化
1.cpp:
1 void main() 2 { 3 double db(10.9); 4 double & rdb(db);//引用必須一開始初始化 5 double dbone(10.8); 6 rdb = dbone;//引用一旦初始化,代碼可以編譯,賦值修改無效, 7 rdb = 8.9; 8 cout << "db=" << db << " dbone=" << dbone << endl; 9 cout << "dbsize=" << sizeof(db) << " rdbsize=" << sizeof(rdb) << endl; 10 cin.get(); 11 }
1.cpp運行結果:
2.cpp:
1 struct MyStruct 2 { 3 void print() 4 { 5 printf("hello world"); 6 } 7 }; 8 struct MyStructM 9 { 10 char & ch1;//引用的本質是一個地址 11 }; 12 13 void main() 14 { 15 cout << sizeof(MyStructM) << endl;//引用的本質就是指針 結果為4 16 cout << sizeof(MyStruct) << endl;//結果是1 表示存在 17 //結構體大小,空結構體一個字節,表示存在 18 //sizeof求結構體,不計入代碼區的內容 19 cin.get(); 20 }
引用的聲明方法:類型標識符 &引用名=目標變量名;
1 double db(10.9); 2 double & rdb(db);//類型標識符 &引用名=目標變量名 3 cout << &db << &rdb << endl;//取地址,沒有類型說明符是取地址
1 double db1 = 10.9; 2 double db2 = 9.8; 3 double * p(&db1);//定義指針初始化 4 5 double * (&rp)(p);//定義引用的指針,用指針初始化 6 7 double * (&rrp)(rp);//引用可以用另外一個引用初始化 8
引用可以用另一個引用初始化
0x02:高級引用
引用一個數組:
1 //int a 2 //int & ra; 3 //1,挖掉變量名,2,加上&,3 起別名 4 int a[5] = { 1, 2, 3, 4, 5 };//棧上 5 int(&ra)[5] (a);//引用數組 6 int *p = new int[5]{6, 7, 8, 9, 10};//堆上 7 int * (&rp)(p);//引用堆,引用指針就可以 8
1 int *p[5] = { &a[0], &a[1], &a[2], &a[3], &a[4] }; 2 3 int * (&rp)[5](p);//第一挖掉數組名,第二(& +別名)
任何數組類型的引用:
1 void main() 2 { 3 int a[3][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } 4 }; 5 6 int *p[3][3] = { &a[0][0], &a[0][1], &a[0][2], 7 &a[1][0], &a[1][1], &a[1][2], 8 &a[2][0], &a[2][1], &a[2][2] }; 9 10 //int * (&rp)[3][3](p); 11 //任何數組類型的引用 12 //第一挖掉變量名 13 //第二加上() 14 //第三加上& 15 //第四加上引用變量名 16 int * (&rp)[3][3](p); 17 18 for (int i = 0; i < 3; i++) 19 { 20 for (int j = 0; j < 3; j++) 21 { 22 cout << (void *)rp[i][j] << " " << *rp[i][j] << endl; 23 } 24 } 25 cin.get(); 26 }
引用可以突破副本機制:
1 double db1 = 10.9; 2 double db2 = 9.8; 3 4 void change(double * & p)//突破副本機制,形參,傳引用,傳地址 5 { 6 p = &db2; 7 } 8 9 10 void main() 11 { 12 double * p(&db1);//定義指針初始化 13 double * (&rp)(p); 14 change(rp);//實際參數傳引用形式參數不是引用不能改變成功 15 cout << *p << endl;//結果為9.8 16 17 cin.get(); 18 }
0x03:超猥瑣的引用
函數指針的引用:
1 void print(char *str) 2 { 3 cout << str << endl; 4 } 5 6 void main() 7 { 8 void (*p)(char *str)(print); 9 p("hello world"); 10 11 void(* &rp)(char *str)(p);//函數指針的引用 12 cin.get(); 13 }
引用結構體數組:
1 struct MyStruct 2 { 3 int a; 4 int & ra; 5 6 }; 7 8 void main() 9 { 10 int num[3]{1, 2, 3};//初始化數組 11 MyStruct st[3]{{ 10, num[0] }, { 20, num[1] }, { 30, num[2] }};//初始化結構體數組 12 MyStruct * p = new MyStruct[3]{{ 10, num[0] }, { 20, num[1] }, { 30, num[2] }};//堆上 13 14 MyStruct *(&rp)(p);//引用結構體指針 15 16 MyStruct (& rst)[3](st);//引用結構體數組 17 for (int i = 0; i < 3;i++) 18 { 19 cout << rst[i].a << " " << rst[i].ra << endl; 20 21 } 22 for (int i = 0; i < 3; i++) 23 { 24 cout << rp[i].a << " " << rp[i].ra << endl; 25 26 } 27 cin.get(); 28 }
引用函數指針數組:
1 int add(int a, int b) 2 { 3 return a + b; 4 } 5 int sub(int a, int b) 6 { 7 return a - b; 8 } 9 int mul(int a, int b) 10 { 11 return a * b; 12 } 13 int divv(int a, int b) 14 { 15 return a / b; 16 } 17 18 void mainY() 19 { 20 //函數指針數組int(*p[4])(int, int); 21 int(*p[4])(int, int){ add, sub, mul, divv }; 22 23 int(*(&rp)[4])(int, int)(p);//引用函數指針數組 24 for (int i = 0; i < 4;i++)//下標循環 25 { 26 cout << rp[i](100, 10) << endl; 27 } 28 for (int(**pp)(int, int) = p; pp < p + 4; pp++)//指針循環 29 { 30 int(** &rpp)(int, int)(pp);//引用二級函數指針 31 cout << (*rpp)(100, 10) << endl; 32 33 } 34 cin.get(); 35 36 }
0x04:右值引用
C++11,引用右值
//如果不是左值,手動先拷貝到內存實體,才能引用
//我們無需拷貝,右值引用,編譯器會自動幫我們拷貝到內存/
1 void print(int && rint)//右值引用,一旦引用常住內存,編譯器自己維護 2 { 3 cout << rint << endl; 4 cout << (void*)&rint << endl; 5 cout << "\n\n"; 6 } 7 8 9 void main() 10 { 11 int x = 30; 12 print(x + 1); 13 14 cout << "\n\n"; 15 print(x + 2); 16 17 cout << "\n\n"; 18 print(x + 3); 19 20 cout << "\n\n"; 21 print(x + 4); 22 cin.get(); 23 24 }
1 void main() 2 { 3 int x = 3; 4 print(x + 1); 5 int && rint(x + 3);//&&引用沒有內存實體的臨時變量 6 cout << rint << endl; 7 cout << "\n\n"; 8 9 cout << rint << endl; 10 cout << (void*)&rint << endl; 11 cin.get(); 12 }
//如果不是左值,手動先拷貝到內存實體,才能引用
//我們無需拷貝,右值引用,編譯器會自動幫我們拷貝到內存/