C++基础02-C++对c的拓展
變量名實質上是一段連續(xù)存儲空間的別名,是一個標號(門牌號)
通過變量來申請并命名內存空間.
通過變量的名字可以使用存儲空間.
變量名,本身是一段內存的引用,即別名(alias). 引用可以看作一個已定義變量的別名。
引用的語法:Type& name = var;
int a=10;??//c編譯器分配4個字節(jié)內存, a內存空間的別名
int &b=a;? //b就是a的引用
3.1.3 規(guī)則
1 引用沒有定義,是一種關系型聲明。聲明它和原有某一變量(實體)的關系。故而類型與原類型保持一致,且不分配內存。與被引用的變量有相同的地址。
2 聲明的時候必須初始化,一經聲明,不可變更。
3 可對引用,再次引用。多次引用的結果,是某一變量具有多個別名。
4 &符號前有數據類型時,是引用。其它皆為取地址。
?
const int a;
int const b;
//第?個第?個意思?樣 代表?個常整形數
const int *c;
//第三個 c是?個指向常整形數的指針(所指向的內存數據不能被修改,但是本?可以修改)
int * const d;
//第四個 d 常指針(指針變量不能被修改,但是它所指向內存空間可以被修改)
const int * const e ;
//第五個 e?個指向常整形的常指針(指針和它所指向的內存空間,均不能被修改)
const?常量是由編譯器處理的,提供類型檢查和作用域檢查
?#define?宏定義由預處理器處理,單純的文本替換 ?
引用作為函數參數
? ? ? ?普通引用在聲明時必須用其它的變量進行初始化,引用作為函數參數聲 明時不進行初始化
引用作為函數的返回值(引用當左值)
I. 當函數返回值為引用時,
? ? ? ? ?若返回棧變量: 不能成為其它引用的初始值(不能作為左值使用)
? ? ? ? ?若返回靜態(tài)變量或全局變量 可以成為其他引用的初始值(可作為右值使用,也可作為左值使用)
? ? ? ? 如果返回值為引用可以當左值
? ? ? ? 如果返回值為普通變量不可以當左值。
普通引用有自己的存儲空間嗎?
? ? ? ? 1)引用在C++中的內部實現是一個常指針
? ? ? ? ? ? ? ?Type& name <===> Type* const name
? ? ? ? 2)C++編譯器在編譯過程中使用常指針作為引用的內部實現,因此引用所占 用的空間大小與指針相同。
? ? ? ? 3)從使用的角度,引用會讓人誤會其只是一個別名,沒有自己的存儲空間。
這是C++為了實用性而做出的細節(jié)隱藏。
從右向左看,&或*哪個離變量近, 哪個便起主要作用。int*&a=p_a; 把int*看成類型
int? b=12;
int? &a=b;
int* p_a=&b;
int* &a=p_a;
const引用
const 引用有較多使用。它可以防止對象的值被隨意修改。因而具有一 些特性。
(1)const 對象的引用必須是 const 的,將普通引用綁定到 const 對象是不 合法的。這個原因比較簡單。既然對象是 const 的,表示不能被修改,引用當然 也不 能修改,必須使用 const 引用。實際上,
? ? ? ? ? ?const int a=1;
? ? ? ? ? ?int &b=a;
這種寫法是不合法 的,編譯不過。
(2)const 引用可使用相關類型的對象(常量,非同類型的變量或表達式)初 始化。這個是 const 引用與普通引用最大的區(qū)別。
? ? ? ? ? const int &a=2; 是合法的。
? ? ? ? ? double x=3.14;
? ? ? ? ? const int &b=a;
也是合法的。
//int &m = 41; //error , 普通引? 引??個字?量 請問字?量有沒有內存地址
const int &m = 43; //c++編譯器 會 分配內存空間
// int temp = 43
// const int &m = temp;
#include <iostream> using namespace std; int main(void) { //1> ?變量 初始化 常引? int x1 = 30; const int &y1=x1; //?x1變量去初始化 常引? //2>?字?量 初始化 常量引? const int a = 40; //c++編譯器把a放在符號表中 //int &m = 41; //error , 普通引? 引??個字?量 請問字?量有沒有內存地址 26 const int &m = 43; //c++編譯器 會 分配內存空間 // int temp = 43 // const int &m = temp; return 0; }?
const引用的原理
const 引用的目的是,禁止通過修改引用值來改變被引用的對象。
結論:
1)const int & e 相當于 const int * const e
2)普通引用 相當于 int *const e
3)當使用常量(字面量)對const引用進行初始化時,C++編譯器會為常量值
分配空間,并將引用名作為這段空間的別名
4)使用字面量對const引用初始化后,將生成一個只讀變量
?
?
內存四區(qū):
1引用的基本語法:
#if 1 #include<iostream> using namespace std; //1 引用沒有定義, 是一種關系型聲明。聲明它和原有某一變量(實體)的關 //系。故 而類型與原類型保持一致, 且不分配內存。與被引用的變量有相同的地 //址。 //2 聲明的時候必須初始化, 一經聲明, 不可變更。 //3 可對引用, 再次引用。多次引用的結果, 是某一變量具有多個別名。 //4 & 符號前有數據類型時, 是引用。其它皆為取地址。 void test01() {int a = 10;int &b = a;cout << a << endl; //10b = 20;cout << a << endl; //20cout << b << endl; //20a = 30;{int *p = &a; *p = 12;cout << *p << endl; //12cout << a << endl; //12}cout << a << endl; //12cout << b << endl; //12} void test02() {int a = 10;int *p = &a;*p = 12;cout << *p << endl; //12cout << a << endl; //12 }void test03() {const int a = 10;int *p = (int *)&a;*p = 12;cout << *p << endl; //12cout << a << endl; //10 }void test04() {int a = 10;int &b = a;int *p = &a;*p = 30;p = &b;*p = 20;int &re = a;re = 50;cout << a << endl; //50cout << b << endl; //50cout << re << endl; //50int ff = 10;re = ff;cout << a << endl; //10cout << b << endl; //10cout << re << endl; //10}void test05() {int a=1, b=0;int &r = a;r = b; //錯誤,不可更改原有的引?關系//float &rr = b; //錯誤,引?類型不匹配 cout<<&a<<&r<<endl; //變量與引?具有相>同的地址。int &ra = r; //可對引?更次引?,表? a 變量有兩個別名,分別是 r 和 ra } void test06() {int a = 10;int &b = a;int c = 20;b = c;b = 50;cout << a << endl; //50cout << b << endl; //50cout << c << endl; //20 b并不是c的引用}void test07() {int a = 10;int &b = a;b = 100;cout << a << endl; //100cout << b << endl; //100int c = 20;b = c;b = 200;cout << a << endl; //200cout << b << endl; //200cout << c << endl; //20 c的值未更改 b并不是c的別名 } int& test08() {int a;return a; //返回的是a的別名,函數調用完釋放a,那么a的引用將不知道指向何處,所以test08()值會亂碼 } int& test09() {int a=0;return a; //返回的是a的別名,函數調用完釋放a,那么a的引用將不知道指向何處,所以test08()值會亂碼const int &a1 = 100; } int main() {//test01();//test02();//test03();//test04();//test05();//test06();//test07();int a = 100;test08() = a;//test08() = a ?//修改局部變量的值 錯誤cout << test08() << endl; //-858993460cout << test09() << endl; //0 //不懂int a1= 100;test09() = a1;cout << test09() << endl; //0cout << a1 << endl; //100return 0; } #endif?2引用當函數參數
#if 1 #include<iostream> using namespace std; void change_value1(int c) { //int c=a; c是局部變量需要復制 重新開辟棧空間c = 100; } void change_value2(int *c) {//int *c=a; 指針c存放a的地址。改變*c就是改變a的值//不需要額外復制*c = 200; } void change_value3(int &c) { //int &c=a; 形參c是實參a的引用,不需要額外復制c = 300; }void test01() {int a = 0;change_value1(a);cout << "change_value1:" << a << endl; //0a = 0;change_value2(&a);cout << "change_value2:" << a << endl; //200a = 0;change_value3(a);cout << "change_value3:" << a << endl; //300 }struct student {int id;char name[64]; }; void PrintStudent1(student s) { //不建議使用 值拷貝cout << s.id << " " << s.name << endl; } void PrintStudent2(student *s) {cout << s->id << " " << s->name << endl; } void PrintStudent3(student &s) {cout << s.id << " " << s.name << endl; } void test02() {student s1 = { 10,"sdsd" };PrintStudent1(s1); //不建議使用PrintStudent2(&s1);PrintStudent3(s1); } int main() {//test01();test02();return 0; } #endif3引用的本質
#if 1 #include<iostream> using namespace std;//當研究引用時,可以將引用當做一個常指針研究 //當使用引用編程時,就把引用理解為變量的別名就OK了 struct typeA {int &a; }; struct typeB {int *a; }; //引用的所占用的大小 跟指針相等 void test01() {cout << "sizeof(struct typeA):" << sizeof(typeA) << endl; //4 32位系統(tǒng)cout << "sizeof(struct typeB):" << sizeof(typeB) << endl; //4 32位系統(tǒng) } struct student {int id;char name[64]; }; //引用聲明時必須初始化 常量聲明時也必須初始化 引用可能是常量 //引用可能是常指針 int * const p; void modify1(int *const a) { //int *const a=main::&a; 可以改變a的值但不能改變a指向*a = 300;//a++; 錯誤 } void modify2(int &a) { //int &a=main::a; //當我們將引用作為函數參數傳遞的時候,編譯器會替我們將實參,取地址給引用a = 200; //對一個引用操作 賦值時,編譯器替我們隱藏*操作 } void modifyStudent(int *const a) { //int *const a 可以改變a的值但不能改變a指向*a = 300;//a++; 錯誤 }void test02() {int a = 10;int &re = a;int *const p = &a; } int main(){test01();return 0; } #endif4常量指針
#if 1 #include<iostream> using namespace std; int main() {int const a = 0; //在常量區(qū)int *const p1 = NULL; //在常量區(qū)//p1++; ERROR*p1 = 30;int const *p2 = NULL; //在常量區(qū)p2++;//*p2 = 40; ERRORreturn 0; } #endif5引用作為函數返回值
#if 1 #include<iostream> using namespace std;int getA1() {int tempValue = 10;return tempValue; } void getA2(int *a) {*a = 20; }int &getA3() {int a = 10;return a; //int &temp=a;將temp傳到外部 返回的是別名 } int &getA4() {static int a = 10;return a; } char *getmen(int num) {char *p = NULL;p = (char *)malloc(num);return p; //值拷貝 }int getmen2(char **pp, int num) {char *p = NULL;p = (char *)malloc(num);*pp = p;return 0; }void test01() {int a = 0;a = getA1(); //將返回值10拷貝給了a。要是有多個結構體會很浪費空間char *pp = NULL;pp = getmen(10);int main_a = 0;main_a = getA3(); //main_a=temp; 值拷貝cout << main_a << endl; //10cout << main_a << endl; //10//引用作為返回值,不要返回局部變量的引用。否則可能會出錯 getA3函數被回收(沒有權限訪問,之前的變量覆蓋)//引用如果當函數返回值的話,函數可以當左值int &main_a_re = getA3();cout << main_a_re << endl; //10cout << main_a_re << endl; //-858993460int &main_a_re1 = getA4(); cout << main_a_re1 << endl; //10cout << main_a_re1 << endl; //10cout << main_a_re1 << endl; //10getA4() = 1000; }int main() {test01();return 0; } #endif6引用指針
#if 1 #define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std;struct teacher {int id;char name[64]; }; int get_mem(struct teacher** tpp) {teacher *tp = NULL;tp = (teacher*)malloc(sizeof(teacher));if (tp == NULL) {return 0;}tp->id = 100;strcpy(tp->name, "li4");*tpp = tp;return 0; } void Free_teacher(struct teacher **tpp) {if (tpp == NULL) {return;}struct teacher *tp = *tpp;if (tp != NULL) {free(tp);*tpp = NULL;} } void test01() {struct teacher *tp = NULL;get_mem(&tp);cout << tp->id << " " << tp->name << endl;Free_teacher(&tp);} int get_mem2(struct teacher * &tp) { //struct teacher *為整體相當于inttp = (struct teacher *)malloc(sizeof(struct teacher));if (tp == NULL) {return -1;}tp->id = 1000;strcpy(tp->name, "wangwu");return 0;} void Free_teacher2(struct teacher * &tp) {if (tp != NULL) {free(tp);tp = NULL;}} void test02() {struct teacher *tp = NULL;get_mem2(tp);cout << tp->id << " " << tp->name << endl;Free_teacher2(tp); } int main() {test01();test02();return 0; } #endif7const引用
#if 1 #include<iostream> using namespace std; void test01() {//如果對一個常量進行引用,則必須是一個const引用//相反 如果一個普通變量,用一個const引用是可以的const int a = 10; //安全性較高//int &b = a; //錯誤 將 "int &" 類型的引用綁定到 "const int" 類型的初始值設定項時,//限定符被丟棄 03C++對C的拓展const int &re = a;int b = 20; //安全性較低const int &re2 = b;// ret2 = 200; 錯誤b = 30;cout << b << endl; //30cout << re2 << endl; //30 const引用的目的是,禁止通過修改引用值來改變被引用的對象。//但可以通過改變被引用的對象改變引用值}void test02() {//int &ref = 10; //錯誤 引用了不合法的內存 不可以const int &ref = 10; //加入const后,編譯器處理方式為:int tmp=10;const int &ref=tmp;對臨時變量的引用//ref =10; //錯誤int *p = (int*)&ref;*p = 1000;cout << ref << endl; //1000 }//引用使用場景:通常用來修飾形參 void showValue(int &val) {val += 1000; //如果只是想顯示內容 而不進行修改就使用const進行修飾cout << "value:" << val << endl; }void showValue(const int &val) {//val += 1000; //編譯錯誤cout << "value:" << val << endl; }void test03() {int a = 10;showValue(a); //1010 } int main() {test01();cout << "--------" << endl;test02();cout << "------------" << endl;test03();return 0; } #endif?
總結
以上是生活随笔為你收集整理的C++基础02-C++对c的拓展的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对tf.nn.softmax的理解
- 下一篇: C++运行界面一闪而过解决