C++對於C故有問題的改進

C++繼承了全部的C特性,而且提供了更豐富的語法和特性(OOP支持、模板支持等),而且擁有和C語言一樣出色的運行效率。針對C語言的固有問題,C++作出了以下的升級:函數

  • 全部變量均可以在須要使用時再定義(C99支持)
  • 忽略register關鍵字,仍然能夠取得register變量的地址
  • 不容許定義多個同名的全局變量(C容許這樣作,而且這些變量最終會被連接到同一塊內存上)
  • struct關鍵字如今能夠用來定義一個全新的類型(C只是定義一個標識符,不是一種類型)
  • 函數聲明中的參數列表爲空則表示void(在C中,能夠傳入任意多的參數)
  • 全部的標識符都必須顯示聲明類型(在C中,默認類型是int)

1、全部變量均可以在須要使用時再定義

在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

2、忽略register關鍵字,仍然能夠取得register變量的地址

在C語言中,register關鍵字用於請求編譯器將變量直接定義在寄存器中(編譯器可能會根據實際狀況忽略這個請求)。然而,這個功能在C++中是一個雞肋,所以大多數C++不會針對register關鍵字進行特殊優化。對象

int main(int argc, char *argv[])
{
    register int a = 0; 
    int *pa = &a; // C語言不容許這樣作,但C++能夠。
    return 0;
}

3、不容許定義多個同名的全局變量

對於老式的C語言編譯器(好比BCC編譯器),容許定義同名的全局變量,而且將它們連接到同一塊內存上。雖然一些現代化的C編譯器(例如gcc, VC)一樣不容許這樣作,可是這仍然是C的一個黑暗地帶。所以,C++徹底禁止了這樣的作法。如今,C++中的同名的全局變量必定會引起編譯錯誤。繼承

int g_v = 1;
double g_v = 2; // 編譯錯誤: 定義同名的全局變量。

int main(int argc, char *argv[])
{
    return 0;
}

4、struct關鍵字如今能夠用來定義一個全新的類型

在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;
}

5、函數聲明中的參數列表爲空則表示void

在C中,函數聲明中的參數列表若是爲空,則意味着該函數能夠接受任意多的實參;而在C++中,這種寫法與void等價:編譯器

int func()
{
    //...
    return 0;
}

int main(int argc, char *argv[])
{
    func(1, 2, 3, 4/*....*/); // C語言容許這樣作,這些變量在函數調用時被壓棧。
                              // C++語言不容許這樣作,由於參數列表被推斷爲void。
    return 0;
}

6、全部的標識符都必須顯示聲明類型

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;
}
相關文章
相關標籤/搜索