C++繼承了全部的C特性,而且提供了更豐富的語法和特性(OOP支持、模板支持等),而且擁有和C語言一樣出色的運行效率。針對C語言的固有問題,C++作出了以下的升級:函數
在C99標準以前,C函數中的全部變量定義都必需要寫在函數的開頭:優化
int main() { return 0; }
void func() { int a, b, i; // 運算代碼... a = 10; // 運算代碼... b = 20; // 運算代碼... for(i = 0; i < 10; i++) { // 運算代碼... } }
這樣作的問題在於:若是函數很是複雜,須要使用的變量不少,那麼很難根據上下文來判斷變量的含義,對於代碼的書寫和閱讀都很不利。所以,自C99標準開始,C支持在變量須要使用時再定義和初始化:設計
void func() { // 運算代碼... int a = 10; // 運算代碼... int b = 20; // 運算代碼... for(int i = 0; i < 10; i++) { // 運算代碼... } }
而對於C++,在語言設計之初就已經支持了這個特性。全部的對象均可以在函數中的任意位置定義。code
在C語言中,register
關鍵字用於請求編譯器將變量直接定義在寄存器中(編譯器可能會根據實際狀況忽略這個請求)。然而,這個功能在C++中是一個雞肋,所以大多數C++不會針對register
關鍵字進行特殊優化。對象
int main(int argc, char *argv[]) { register int a = 0; int *pa = &a; // C語言不容許這樣作,但C++能夠。 return 0; }
對於老式的C語言編譯器(好比BCC編譯器),容許定義同名的全局變量,而且將它們連接到同一塊內存上。雖然一些現代化的C編譯器(例如gcc, VC)一樣不容許這樣作,可是這仍然是C的一個黑暗地帶。所以,C++徹底禁止了這樣的作法。如今,C++中的同名的全局變量必定會引起編譯錯誤。繼承
int g_v = 1; double g_v = 2; // 編譯錯誤: 定義同名的全局變量。 int main(int argc, char *argv[]) { return 0; }
在C語言中,struct
關鍵字僅僅用於將多個其餘數據類型組合在一塊兒,採起必定的對齊方式佔用一塊連續的內存空間。然而,它定義的只是一個標識符,沒法直接使用這個標識符來定義變量,而必需要使用類型別名的方式來爲這個標識符定義類型名稱。C++針對struct
作了重要的擴充。如今,struct
被用來定義類類型,不只直接定義一個新類型,還支持類相關的寫法(更多的被用於定義POD
(Plain Old Data)類型)。內存
struct my_struct { int a; float b; double c; }; int main(int argc, char *argv[]) { // C風格的變量定義。 struct my_struct a; // C++風格的對象定義。 my_struct c; return 0; }
在C中,函數聲明中的參數列表若是爲空,則意味着該函數能夠接受任意多的實參;而在C++中,這種寫法與void等價:編譯器
int func() { //... return 0; } int main(int argc, char *argv[]) { func(1, 2, 3, 4/*....*/); // C語言容許這樣作,這些變量在函數調用時被壓棧。 // C++語言不容許這樣作,由於參數列表被推斷爲void。 return 0; }
C語言中容許使用函數的默認返回類型和變量的默認類型,然而對此C++有更嚴格的要求,必須顯示地聲明變量的類型,或者使用自動類型推斷(C++11)。編譯
// C語言容許這樣作,默認的返回類型爲int。 // C++語言不容許這樣作,必須顯示地指定返回類型,或者使用自動類型推斷。 func() { return 5; } // C++容許的作法 int func() // 顯示指定返回類型 { return 5; } auto func() // 自動推斷返回類型(C++11) { return 5; } decltype(auto) func() // 自動推斷返回類型(C++11) { return 5; }