首頁  >  文章  >  後端開發  >  C/C++差別有哪些?很多人都不知道的比較方法

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

php是最好的语言
php是最好的语言原創
2018-07-24 17:31:412214瀏覽

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. 預設值: 預設參數是宣告或定義函數時為函數的參數指定一個預設值。在呼叫函數時,如果沒有指定實參則採用該預設值,否則,使用指定的實參。

  6. //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;
}
//如果用引用时不想改变实参的值,则给引用前加const
void 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 = &#39;c&#39;;    cout << a ;    cout << b << &#39;\n&#39;;    cout << c << endl;    cout << a << " " << b << " " << c << endl;    cin >> a ;    cin >> b >> c;    return 0;
}// cout:标准命名空间重输出流对象  <<输出操作符   // cin:标准命名空间重输入流对象   >>输入操作符

相关推荐:

C# 中的 == 和 equals()有什么区别  

C# 中的 == 和 equals()区别       

视频:C++视频教程

以上是C/C++差別有哪些?很多人都不知道的比較方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn