C++修煉篇:01 從C到C++的升級

引言:本文意在完成一場從C到C++世界的平滑過渡,因此要求讀者應具備一定的C語言基礎功底。

文章嚮導

  • C與C++的關係
  • C++做了哪些升級?

一、C與C++的關係
C與C++的關係並不能簡單地概括爲僅多了兩個+號而已,兩者實際上既有區別又有聯繫,且並無所謂的何者好壞之說。簡單說來,C++其實是一種更好的C語言,只不過兩者適用場景並不相同。
這裏寫圖片描述
由上圖可知,C++繼承了C的所有特性,也就是完全地兼容C語言。同時,C++在C的基礎上提供了更多的語法和特性(++的由來:類型加強、函數加強)。C++所要達到的目標是運行效率與開發效率的同一。

二、C++做了哪些升級?

1.更爲強調語言的實用性

int c = 0;

for(int i=1; i<=Numoftask; i++)
{
    for(int j=1; j<Numoftask; j++)
    {
        c += i * j;
    }
}

上面的程序片段是C++中的常見寫法,與C語言(標準規範下)中的變量必須定義在作用域開始的位置處相比,C++則顯得更爲靈活:所有的變量都可以在使用時再定義,這點正如上面的循環變量i和j。

2.C++編譯器獨特的優化方式
C++中依然支持register關鍵字(但實際只是爲了兼容C,效果上來看純屬雞肋),但與C語言相比有着如下的區別:

  • C語言無法獲取register變量的地址,而C++卻能夠做到。
  • C++編譯器發現程序需要取register變量的地址時,register對變量的聲明將會無效。

另外,在C語言中重複定義多個同名的全局變量是合法的(因爲此時多個同名的全局變量最終會被鏈接到全局數據區的同一個地址空間上),但在C++中則不允許重複定義多個同名的全局變量。
爲了理解上述所說,不妨看下面這樣一個實際的例子:

#include <stdio.h>

int g_v;
int g_v; //在c++中,此行會報錯

int main(int argc, char *argv[])
{
    printf("Begin...\n");

    int c = 0; //在C中,此處會報錯

    for(int i=1; i<=3; i++) //在C中,此處會報錯
    {
        for(int j=1; j<=3; j++)
        {
            c += i * j;
        }
    }

    printf("c = %d\n", c);

    register int a = 0; //在C中,此處會報錯

    printf("&a = %p\n", &a); //在C中,此處會報錯
    printf("End...\n");

    return 0;
}

3.struct關鍵字的加強

/*C語言中的結構體書寫*/
typedef struct _tag_student Student;

struct _tag_student
{
    const char* name;
    int age;
};

/*C++中的結構體書寫*/
struct Student
{
    const char* name;
    int age;
}

上面展示的爲C與C++中的結構體等價寫法,可明顯發現兩者的區別:-C語言中struct定義的標識符並不是一種新的類型,而C++中的struct卻用於定義一種全新的類型。

4.隱式聲明與函數參數
首先,應該明確的是C++中所有的標識符都必須顯示聲明類型,即在C++中不應該寫出如下的代碼:

f()
{
    printf("i = %d\n", i);
}

上面的函數f()在C語言中表示默認返回值爲int,且可接收任意多的參數,但在C++中這樣寫是沒法通過編譯的。另外,值得注意的是C++中 int f()和int f(void)具有相同的意義。

5.const關鍵字的升級
這裏寫圖片描述
上圖對比了const關鍵字在C語言與C++中的異同之處,爲了更好的理解圖中的結論,請看如下兩個示例。

/*test.c*/
#include <stdio.h>

int main()
{
    const int c = 0;
    int* p = (int*)&c;

    printf("Begin...\n");

    *p = 5;

    printf("c = %d\n", c);  //5
    printf("&p = %p, p = %p, &c = %p\n", &p, p, &c); 
    printf("*p = %d\n", *p); //5
    printf("End...\n");

    return 0;
}
/*test.cpp*/
#include <stdio.h>

int main()
{
    const int c = 0;
    int* p = (int*)&c;

    printf("Begin...\n");

    *p = 5;

    printf("c = %d\n", c);  //0
    printf("&p = %p, p = %p, &c = %p\n", &p, p, &c); 
    printf("*p = %d\n", *p); //5
    printf("End...\n");

    return 0;
}

這裏主要分析第二個例子,也就是C++中的情形。首先看下完整的運行結果:
這裏寫圖片描述
從圖中可以明確看到編譯器給const常量c分配了存儲空間,但卻並未使用其存儲空間中的值。要理解這點則需明白之前提及的“符號表(編譯器的一種數據結構)”,C++中定義的const常量,編譯器會將其存入符號表中,當要使用常量時則直接從符號表中取值進行替換,但爲了兼容C語言可能會爲其分配存儲空間,但卻不會使用其中的值。有點繞?那不妨看看下面這張草圖:
這裏寫圖片描述

Notes:實際上還有其他的升級方面,但這會牽涉到C++獨有的知識點,因此筆者想將其放在後續的內容中來論述。

參閱資料
C++ Primer Plus(第6版)
狄泰軟件學院-C++深度解析教程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章