第七天2017/04/14(C++对C的扩充,C++与C的区别,C++的基础知识)
生活随笔
收集整理的這篇文章主要介紹了
第七天2017/04/14(C++对C的扩充,C++与C的区别,C++的基础知识)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
1、C++對C的擴(kuò)展
(1)命名空間(作用域):namespace在C中,只有一個全局作用域,C語言的所有的全局標(biāo)識符共享同一個作用域,標(biāo)識符之間可能發(fā)生命名沖突。C++中提出了命名空間的概念,命名空間將全局作用域分成不同的部分,不同命名空間中的標(biāo)識符可以同名而不會發(fā)生沖突,命名空間可以相互嵌套,全局作用域也叫默認(rèn)命名空間。在C++中,名稱name可以使符號常量、變量、宏、函數(shù)、結(jié)構(gòu)、枚舉、類和對象等,在大規(guī)模程序設(shè)計中,以及在程序員使用各種各樣的C++庫時,這些標(biāo)識符發(fā)生“命名沖突”,標(biāo)準(zhǔn)C++引入了namespace關(guān)鍵字,可以很好地控制標(biāo)識符的作用域。namespace是指標(biāo)識符的各種可見問題。C++標(biāo)準(zhǔn)程序庫中的所有標(biāo)識符(形如:endl/cout/cin等)都被定義在一個名為std的namespace中。命名空間定義:namespace name { ... }命名空間使用:using namespace name; (2)regiter關(guān)鍵字的增強 “請求”編譯器讓局部變量a直接放在寄存器里面,速度快。 //1.在c語言中register修飾的變量不能取地址,但是在C++編譯器中可以取地址,在C++編譯器中動了手腳。 //2.C++編譯器發(fā)現(xiàn)程序中需要取register變量的地址時,register對變量的聲明變得無效。 //3.早期的C語言編譯器不會對代碼進(jìn)行優(yōu)化,因此register變量是一個很好地補充。 (3)C++中,不允許定義多個同名的全局變量。int a;int a = 0; //在C語言中編譯可以成功,但是在C++中編譯會失敗。 【總結(jié)】 C語言中多個同名的全局變量最終會被鏈接到全局?jǐn)?shù)據(jù)區(qū)的同一個地址空間上。 C++直接拒絕這種二義性的行為 (3)struct類型加強 (4)C++所有變量和函數(shù)必須有類型(對類型檢查將會更加嚴(yán)格) 結(jié)論:C語言中的默認(rèn)類型在C++中是不合法的。在C語言中:int f();表示返回值為int,接受任意參數(shù)的函數(shù)int f(void);表示返回值為int的無參函數(shù)在C++中:int f();和int f(void);具有相同的意義,都表示返回int的無參函數(shù)C++更加強調(diào)類型,任何程序元素都必須顯示的指明類型。 (5)C++引出bool類型 bool類型只有兩個值:1和0 bool類型占用1個字節(jié) (6)三目運算符在C和C++中的不同:C++對三目運算符做了優(yōu)化。在C中:三目運算符不可以作“左值”,它返回的是一個值(a<b?a:b) = 30; //錯誤在C++中:三目運算符可以作“左值”,C++編譯器對它動了手腳,它返回的是一個變量(但是:如果三目運算符的a、b中有一個是常量值,則不能作為左值)(a<b?a:b) = 30; //正確 做了什么手腳: *((a<b?&a:&b)) = 30; //正確 (a<b?a:200) = 30; //錯誤 【注解】當(dāng)左值的條件:這段內(nèi)存空間可以被寫。 (7)const關(guān)鍵字 #include<iostream> using namespace std; int main() {const int a;int const a; //二者意義相同const int *c;int const *c; //二者意義相同int *const d;const int* const e; } ===================================================== 一般的const經(jīng)常用作修飾結(jié)構(gòu)體形參,防止結(jié)構(gòu)體指向 中的變量被修改因此,我們先介紹下結(jié)構(gòu)體作為形參的下面兩種case: ===================================================== 再次復(fù)習(xí),深入了解:結(jié)構(gòu)體作為形參、結(jié)構(gòu)體的指針作為形參 #include<iostream> using namespace std;struct student {int age;char name[100]; };void f1( struct student stu) //結(jié)構(gòu)體作為形參 //傳入的是結(jié)構(gòu)體變量,此時:相當(dāng)于 “形參=實參” 的賦值操作,相當(dāng)于淺拷貝 //在f1中對形參進(jìn)行修改,并不會導(dǎo)致實參的值發(fā)生任何變化 {stu.age = 100;strcpy(stu.name,"New"); }void f2( struct student* stu) //結(jié)構(gòu)體指針作為形參 //傳入的是結(jié)構(gòu)體的地址,此時形參和實參指向同一個內(nèi)存塊 {(*stu).age = 100;strcpy((*stu).name,"New"); }int main() {struct student s = {20, "Old"};f1(s);cout<<s.age<<"+"<<s.name<<endl; //在f1中進(jìn)行修改,但是在main并不會變化f2(&s);cout<<s.age<<"+"<<s.name<<endl; //在f2中進(jìn)行修改,在main中會發(fā)生變化 } ===================================================== void f2(const struct student* stu) //此時用const修飾結(jié)構(gòu)體指針變量, //此時會導(dǎo)致編譯失敗:因為在f2函數(shù)體中對結(jié)構(gòu)體的內(nèi)容作了修改 {(*stu).age = 100;strcpy((*stu).name,"New"); } =====================================================下面介紹一個“奇怪的東東”:把同樣的代碼,放在C和C++程序中編譯的結(jié)果竟然不一樣!代碼如下: #include "stdio.h" int main() {const int a = 10; //a是一個只讀的常量,按照理論a應(yīng)該不能被修改printf("修改之前 a = %d\n",a);//a = 100; //注:此時編譯失敗,a不能被修改!疑問:那么a就不能被修改了么? //答案:在C中,a被修改,但是在C++中a沒被修改,具體情況見下:int *p = NULL;p = (int*)&a; //把a的地址賦給p :先取a的地址(&a是const int*類型),再把const int*轉(zhuǎn)成int*類型,最后賦值給p*p = 100; //用*p對a進(jìn)行間接的修改,在C中修改成功,但是在C++中修改卻失敗printf("修改之后 a = %d\n",a);getchar(); } 執(zhí)行結(jié)果竟然不一樣: 在C中:修改之前 a = 10修改之后 a = 100 //發(fā)現(xiàn),a竟然被修改 在C++中:修改之前 a = 10修改之后 a = 10 //發(fā)現(xiàn),a竟然沒被修改(這就是C++的牛逼之處,可以更好地使const修飾的變量不被修改) 【結(jié)論】在C語言中,const是一個冒牌貨,const是一個只讀變量,可以通過地址繞過const關(guān)鍵字并且對const修飾的變量進(jìn)行間接修改;但是C++卻怎么都繞不過const,const在C++中是一個常量,沒法對const修飾的變量進(jìn)行修改。 【疑問1:為什么發(fā)生上面的情況呢?】在C++中,通過const修飾的東西,會變成什么樣子的呢?當(dāng)寫完const int a = 10;時,會把上面的信息放在C++里面的符號表中,形如:key = valuea 10... ... 當(dāng)你去用a的時候,C++編譯器會從符號表里邊拿數(shù)據(jù),因此此處的a就是“名副其實”的“真正意義上”的常量。 【疑問2:&a能取到a的地址么?此時的*p又是多少?】 p = (int*)&a; *p = 100;答:當(dāng)執(zhí)行到p = (int*)&a;中的取地址&a時,此時C++編譯器會給a變量分配一個內(nèi)存,并且把a的值10放在該地址中,此時p的值確實等于a的地址。在進(jìn)行*p = 100;后*p的值就是100。 這樣,C++編譯器既做到了對C編譯器的兼容,又做到了對const常量。 【小知識】#define與const的作用域不同 #include "stdio.h" void f1() { #define a 10 //a在f2中可用const int b = 10; //b在f2中不可用 }void f2() {printf("a = %d",a);//printf("b = %d",b); 編譯失敗 }int main() {f1();f2(); }引用專題
【普通引用】 1、變量名的回顧變量名實質(zhì)上是一段連續(xù)存儲空間的別名程序中通過變量名來申請內(nèi)存空間通過變量名可以使用內(nèi)存 問題1:對一段連續(xù)內(nèi)存空間只能取一個別名么?答:不是,引出“引用”。 2、引用是C++中的概念,屬于C++對C的擴(kuò)展 引用能起到指針的作用 可讀性更高 3、引用有內(nèi)存空間么? 答:引用也有內(nèi)存空間! #include <iostream> using namespace std; struct student {char &a;char &b; }; int main() {cout<<sizeof(struct student)<<endl; //答案: 8 } 為什么結(jié)果是8?引用的本質(zhì)是什么呢?答:引用在C++中的內(nèi)部實現(xiàn)是一個常量指針:type &name <-->type* const name。C++編譯器在編譯過程中使用常指針作為引用的內(nèi)部實現(xiàn),因此引用所占用的內(nèi)存大小與指針相同。 【結(jié)論】引用在實現(xiàn)上,只不過是吧間接賦值成立的三個條件的后兩步合二為一:當(dāng) 實參穿給形參引用的時候,只不過C++編譯器幫我們程序員手工取了一個實參地址, 傳給形參引用(常量指針)3、C++引用注意事項當(dāng)函數(shù)返回值為一個引用時,若返回值為“棧變量”,則不能成為其它引用的初始值,不能作為左值使用。若返回值為“靜態(tài)變量”或“全局變量”,則可以成為其它引用的初始值,既可作為右值使用,也可以作為左值使用。總結(jié)
以上是生活随笔為你收集整理的第七天2017/04/14(C++对C的扩充,C++与C的区别,C++的基础知识)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第六天2017/04/11(2:Linu
- 下一篇: 第七天2017/04/14(引用与con