C/C++區別有哪些?很多人都不知道的比較方法

來源:互聯網
上載者:User
C/C++應該從關鍵字的個數、源檔案、變數定義或聲明位置、函數、預設參數幾個方面進行比較,如果你總是搞混,看了這篇文章會協助到你。

C/C++從以下幾個方面的比較:

  1. 關鍵字的個數:
    C語言:C99版本,32個關鍵字
    C++:C98版本,63個關鍵字

  2. 源檔案:
    C源檔案尾碼.c,C++源檔案尾碼.cpp,如果在建立源檔案時什麼都不給,則預設是.cpp

  3. 變數定義或聲明位置:
    C語言必須在第一行定義;C++不做要求

  4. 函數:
    (1)傳回值
    C語言中,如果一個函數沒有指定傳回值類型,預設返回int型;
    C++中,對於函數傳回值的檢測更加嚴格,如果一個函數沒有傳回值,則必須指定為void.
    (2)參數列表
    C語言中,如果函數沒有指定參數列表時,預設可以接受任意多個參數;但在C++中,因為嚴格的參數類型檢測,沒有參數列表的函數,預設為void,不接受任何參數。

  5. 預設參數:
    預設參數是聲明或定義函數時為函數的參數指定一個預設值。在調用該函數時,如果沒有指定實參則採用該預設值,否則,使用指定的實參。

//1.實現預設參數void Test(int a = 50){    cout << a << endl;}int main(){    Test();    // 輸出50    Test(100); // 輸出100}


(1)全預設參數:將所有參數的預設值全部給出//代碼

// 實現全預設參數void Test(int a = 1,int b = 2,int c = 3){    cout << a << "" <<" "<< b << "" <<" "<< c << endl; }int main(){    Test();//1 2 3    Test(100);//100 2 3    Test(100, 200);//100 200 3    Test(100, 200, 300);//100 200 300}

(2)半預設參數:規定,預設值只能從右往左傳//代碼

// 實現半預設參數   註:預設值只能從右往左傳void Test1(int a = 1, int b = 2, int c = 3){    cout << a << "" << " " << b << "" << " " << c << endl;}void Test2(int a , int b = 2, int c = 3){    cout << a << "" << " " << b << "" << " " << c << endl;}void Test3(int a , int b , int c = 3){    cout << a << "" << " " << b << "" << " " << c << endl;}void Test4(int a = 1, int b , int c = 3)//不能通過編譯,因為它違背了預設值只能從右往左依次來給這一規定{    cout << a << "" << " " << b << "" << " " << c << endl;}void Test5(int a = 1, int b = 2, int c )//不能通過編譯,因為它違背了預設值只能從右往左依次來給這一規定{    cout << a << "" << " " << b << "" << " " << c << endl;}void Test6(int a = 1, int b , int c )//不能通過編譯,因為它違背了預設值只能從右往左依次來給這一規定{    cout << a << "" << " " << b << "" << " " << c << endl;}void Test7(int a , int b = 2, int c )//不能通過編譯,因為它違背了預設值只能從右往左依次來給這一規定{    cout << a << "" << " " << b << "" << " " << c << endl;}int main(){    Test1();//1 2 3}

注意:

a. 帶預設值的參數必須放在參數列表的最後面。b. 預設參數不能同時在函式宣告和定義中出現,只能二者則其一,最好放在函式宣告中。c. 預設值必須是常量或全域變數。

C語言不支援預設參數

函數重載

  • 函數重載指在同一範圍中聲明幾個功能類似的同名函數,這些同名函數的形參列表(個數、類型、類型的次序)必須不同。

//函數重載void Add();void Add(int a);//行參個數不一樣void Add(char b);//行參類型不同void Add(int a, char b);void Add(char a, int b);//行參類型的次序不同
  • 僅僅傳回值的類型不同,是不能構成函數重載的。

//僅僅傳回值的類型不同,是不能構成函數重載的void Add(int a, int b){}int Add(int a, int b){    return a + b;}int main(){    Add(1, 2);//因為這樣會造成調用不明確,兩函數都可以被調用    return 0;}
  • C++支援函數重載的原因:VS編輯器在底層將函數參數的類型編譯到函數的名字中,因此原函數名就被換成了另外一個獨一無二的名字。

int Add(int a, int b);    // ?Add@@YAHHH@Zchar Add(int a, int b);   // ?Add@@YADHH@Zchar Add(char a, char b); // ?Add@@YADDD@Z
  • C語言不支援函數重載的原因:所產生的新的函數名還是相同的。只是在函數名前加了_

  • C++中將函數按C語言風格編譯,只需在函數前加 extern “c”

extern "C" int Add(char a, int b);

引用

C語言中函數有兩種傳參方式:傳值傳址

傳值:在函數調用過程中會產生一份臨時變數用形參代替,最終把實參的值傳遞給新分配的臨時變數即形參。
傳值優點:函數的副作用不會影響到外部實參。
傳值缺點:不能通過修改參數來改變外部實參。

傳指:在函數調用過程中會產生一份臨時變數用形參代替,最終把實參的地址傳遞給新分配的臨時變數。
傳指優點:節省空間的,效率高,改變參數可以改變外部實參。
傳指缺點:指標不安全,函數的副作用會影響外部實參。

C++中

引用:
(1)概念:引用不是新定義一個變數,而是給已存在變數取了一個別名,編譯器不會為引用變數開闢記憶體空間,它和它的引用變數共用同一塊記憶體空間。
(2)形式:類型& 引用變數名=引用實體

//引用int main(){    int a = 10;    int& ra = a;    printf("%p\n", a);    printf("%p\n", ra);//ra和a的地址相同,說明ra和a是同一個實體,他們共用同一塊記憶體空間    ra = 3;    printf("%d\n", a);//3    return 0;}

註:

   a. 引用在定義時,必須初始化。   b. 一個變數可以被多次引用。   c. 引用一旦引用了一個實體,就不能在引用其他實體。   d. 引用變數的生命週期比實體的生命週期短。

(3)常引用

常引用int main(){    const int a = 1;    //int& ra = a;//編譯會出錯,因為實體a是常量    const int& ra = a;    double b = 12.34;    //int& rb = b;//編譯會出錯,因為類型不同    const int& rb = b;    printf("rb=%d\n", rb);//rb=12    b = 5.0;    printf("b=%f\n", b);//b=5.0    printf("rb=%d\n", rb);//rb=12    //b的值改變,但rb的值並沒有隨之改變,說明rb和b是兩個不同的實體}

(4)數組引用

//數組引用int a[10];//數組a的類型為 int[10]int(&ra)[10] = a;

(5)引用情境:
a.用引用作為函數的參數來改變實參。

void Swap(int* pLeft, int* pRight){    int temp = *pLeft;    *pLeft = *pRight;    *pRight = temp;}void Swap(int& left, int& right){    int temp = left;    left = right;    right = temp;}//如果用引用時不想改變實參的值,則給引用前加constvoid Swap(const int& left, const int& right);int main(){    int a = 10;    int b = 20;    Swap(&a, &b);//通過傳地址來改變實參    printf(" a=%d ", a);    printf(" b=%d\n", b);    Swap(a, b);//通過引用來改變實參    printf(" a=%d ", a);    printf(" b=%d\n", b);}

b.用引用變數作為函數的傳回值 //代碼

情形1:int& FunTest(){    int a = 10;    return a;}int main(){    int b = FunTest();//將函數的傳回值賦給了b    printf("b=%d\n", b);//b=10    printf("b=%d\n", b);//b=10    printf("b=%d\n", b);//b=10    return 0;}情形2:int& FunTest2(){    int a = 10;    return a;}int main(){    int& b=FunTest2();//將函數的傳回值作為實體,    printf("b=%d\n", b);//b=10    printf("b=%d\n", b);//隨機值    printf("b=%d\n", b);//隨機值    return 0;}情形3:int& FunTest3(int& a){    a = 10;    return a;}int main(){    int b;    int& rb = FunTest3(b);    printf("b=%d\n", b);//b=10    printf("rb=%d\n", rb);//rb=10    printf("rb=%d\n", rb);//rb=10    printf("rb=%d\n", rb);//rb=10    return 0;}注意:不能返回棧空間上的引用

傳值、傳指、引用 效率比較

//比較struct BigType{    int array[10000];};void FunTest(BigType bt)//傳值或傳址{}void FunTest(BigType& bt)//引用{}void TestFunTestRumTime(){    BigType bt;    size_t Start = GetTickCount();    for (i = 0; i < 1000000; i++)    {        FunTest(bt);//傳值或傳引用        FunTest(&bt);//傳址    }    size_t End = GetTickCount();    printf("%d\n", End - Start);}//此代碼檢測出傳值最慢,而傳址和引用速度快且用時差不多相同

引用和指標有什麼區別?

相同點:

  • 列表內容

  • 底層的處理方式相同,都是按照指標的方式實現的。

  • 引用變數在底層所對應指標的類型:

  • 引用變數實體的類型* const

不同點:

  • 引用必須要進行初始化;指標不作要求。

  • 普通類型的指標可以在任何時候指向任何一個同類型對象;而引用一旦引用一個實體,就不能再引用其他實體。

  • 指標++:指向下一個地址; 引用++:給數值++。

  • 在sizeof中含義不同:引用結果為參考型別的大小;而指標始終是 地址*空間所佔位元組個數。

  • 指標需要手動定址;而引用通過編譯器定址。

  • 引用比指標使用起來相對安全。

命名空間

在C++中,變數、函數和類都是大量存在的,這些變數、函數和類的名稱將都存在於全域命名空間中,會導致很多衝突,使用命名空間的目的是對標識符的名稱進行本地化,以避免命名衝突或名字汙染。

  • 命名空間的定義

//命名空間namespace N1{    int a = 30;    void FunTest()    {        printf("N1::FunTest()\n");    }}//N1的命名空間int a = 20;void FunTest(){    printf("::FunTest()\n");}//在全域範圍中int main(){    int a = 10;    printf("%d\n", a);    printf("%d\n", ::a);    ::FunTest();    printf("%d\n", N1::a);    N1::FunTest();    return 0;}//命名空間的嵌套namespace N2{    int a = 40;    void FunTest()    {        printf("N2::FunTest()\n");    }    namespace N3    {        int a = 50;        void FunTest()        {            printf("N2::N3::FunTest()\n");        }    }}int main(){    N2::FunTest();    N2::N3::FunTest();    return 0;}// 在同一個工程裡允許存在多個相同名稱的命名空間,編譯器最後會合成到同一個命名空間中namespace N1{    int b = 70;    void Test()    {        printf("N1::Test()\n");    }}
  • 說明
    a.一個命名空間就定義了一個新的範圍,命名空間中的所有內容都局限於該命名空間中。
    b.沒有名稱的命名空間只能在當前檔案中使用,它裡面定義的變數相當於工程裡面的全域變數。

  • 命名空間的使用

//命名空間的使用namespace N1{    int a = 1;    int b = 2;    int c = 3;    /*void FunTest1()    {}    void FunTest2()    {}*/}//法二:using N1::b;//法三:using namespace N1;int main(){    int a = 4;    //法一:    printf("a=%d\n", N1::a);//a=1    printf("b=%d\n", b);//b=2    printf("c=%d\n", c);//c=3}

C++輸入輸出:

//代碼

//C++輸入輸出#include <iostream>using namespace std;//std標準命名空間int main(){    int a = 10;    double b = 3.14;    char c = 'c';    cout << a ;    cout << b << '\n';    cout << c << endl;    cout << a << " " << b << " " << c << endl;    cin >> a ;    cin >> b >> c;    return 0;}// cout:標準命名空間重輸出資料流對象  <<輸出操作符   // cin:標準命名空間重輸入資料流對象   >>輸入操作符
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.