天天看點

1.C和C++差別,以及const分析(底層const/頂層const)

從本章起開始從0學習C++,本章主要内容:

  • 1)C和C++的基本差別
  • 2)C和C++的const差別

1.C++和C差別

1.1 C++更強調語言的實用性,所有變量都可以在需要時再定義

比如:

for(int i=0;i<100;i++);           

複制

1.2 C++不允許定義多個同名全局變量,而C卻可以重複定義

1.3 C++的register隻是個相容作用

1.4 C++的所有辨別符都必須有聲明類型

比如,在C中:

f(): 表示預設傳回值是int,可以接受任意個int型參數的函數

在C++中:

int f() int f(void)表示都一樣,沒有參數,傳回值為int型的函數

int f(i): 由于i沒聲明類型,會報錯

1.5 結構體更新

例如,在C中定義一個結構體:

typedef student_type student;   //聲明

struct student_type{
char *name;
int age;
};

struct student_type student1={"Li",20};
/*或者*/
student  student2={"Zhang",20};           

複制

而在C++中,隻需要這麼寫:

struct student_type{
char *name;
int age;
};

student_type student2={"Zhang",20};   //不需要strcut再次聲明           

複制

C和C++的const差別

2. C中的const

2.1 介紹

C語言中的const隻是讓變量變為隻讀屬性,其本質還是變量,不是真正意義上的常量(隻有enum枚舉定義的才是常量).

注意:const變量不能被直接指派,但是可以通過指針來修改const變量.

由于const局部變量會存在棧裡,而const全局變量會存在隻讀存儲記憶體上

是以我們可以通過指針來修改const局部變量,但是修改const全局變量,會使程式崩潰.

2.2修改const執行個體

1)執行個體1-通過指針來修改const局部變量

代碼如下:

#include <stdio.h>
int main()
{
    const int c = 0; //const局部變量

    int* p = (int*)&c;
    *p = 5;          //通過指針修改const變量

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

複制

輸出結果:

1.C和C++差別,以及const分析(底層const/頂層const)

2)執行個體2-通過指針來修改const全局變量

代碼如下:

#include <stdio.h>
const int c = 0; //const全局變量
int main()
{
    int* p = (int*)&c;
    *p = 5; //修改const變量
    printf("c = %d\n", c);
    return 0;
}           

複制

輸出結果:

1.C和C++差別,以及const分析(底層const/頂層const)

由于指針修改隻讀存儲區的資料,是以導緻程式崩潰

3. C++中的const

3.1 介紹

在C++中,const變量則是真正的常量了,定義時會将其放入符号表中.

是以編譯途中遇到使用const變量時,則直接從符号表中取出常量.

隻要當該const變量為全局(使用extern聲明過),或者被使用&操作符時,才會被配置設定存儲空間.

接下來,我們以一個例子來分析存儲空間

代碼如下:

#include <stdio.h>
int main()
{
    const int c = 0;    //const局部變量

    int* p = (int*)&c; //使用&操作符,會配置設定空間

    *p = 5;  

    printf("c = %d,*p=%d\n", c,*p);
    return 0;
}           

複制

輸出結果:

1.C和C++差別,以及const分析(底層const/頂層const)

為什麼輸出結果會有兩個不同的值?

這是因為使用&c時,會從符号表中取出c的值,并将0存在一個新的配置設定空間位址裡,是以*p修改的隻是配置設定出來的空間位址内容,而c還是常量.

3.2 const和define差別

是不是感覺C++中的const和 define宏定義一樣?其實不一樣!

  • const常量: 由編譯器處理,它會對const常量進行類型檢查和作用域檢查
  • define宏定義: 由預處理器處理,直接進行文本替換,不會進行各種檢查

(預處理器是執行編譯器之前運作的程式,用來删除注釋,宏變量轉換等)

接下來,我們以一個例子來分析const和define

代碼如下:

#include <stdio.h>
void f()
{
    #define a 3        //定義宏
    const int b = 4; //定義局部變量
}

int main()
{  
    f();   
    printf("a=%d",a);

    //printf("b=%d",b);
    return 0;
}           

複制

輸出結果:

1.C和C++差別,以及const分析(底層const/頂層const)

這是因為執行預處理器時,會将遇見到的所有a變為3,是以編譯器看到的是printf("a=%d?imageView2/2/w/1620",3);

而取消//printf("b=%d",b); 屏蔽後,程式則會報錯,是因為b的作用域隻在f()函數裡有效.

3.3 指針const

指針const分為兩種: 底層const, 頂層const

(普通變量的const(或引用)永遠是頂層const,也就是說,const int 和int const本質都一樣)

1)底層const(位于*左側)

常量指針,表示指向的對象是個常量,不能修改其内容,隻能更改指針指向的位址.

其實很好了解,比如 const int *p, 修飾*p是個const常量.而*p是指向對象的内容.是以表示指向對象的内容是常量

但是可以通過其它方式修改内容,例如:

int a=1,b=3;

const int *p=&a;     //底層const

//*p=2;              //錯誤,無法修改*p指向的a裡面内容

a=2;                 //正确,通過其它方法來修改*p的内容
printf("%d\n",*p);

p=&b;                //正确,可以更改指針指向的位址
printf("%d\n",*p);           

複制

輸出結果:

2
3           

複制

2)頂層const(位于*右側)

指針常量,表示不能更改指針指向的位址,隻能修改其内容(定義時必須被初始化)

其實很好了解,比如 int * const p, 修飾 p是個const常量.而 p是指向對象的位址.是以表示指向對象的位址是個常量

和引用非常相似,例如:

int a=1;
int b=3;

//int *const p;    //錯誤,沒有被初始化

int *const p=&a;   //頂層const

//p=&b;            //錯誤,不能更改指針指向的位址

*p=2;              //正确,修改a的值等于2           

複制

3.4 頂層const變量可以替代mutable變量

1) mutable介紹

mutable 是為了突破 const 的限制而設定的。被 mutable 修飾的變量,将永遠處于可變的狀态,即使在一個 const 函數中,甚至結構體變量或者類對象為 const,其 mutable 成員也可以被修改。

示例1:

class Test{
    
    mutable int mval; 
public:
    Test():mval(0) 
    {
    } 
    void setVal(int num) const 
    {
        mval=num; 
        cout<<mval<<endl;     //列印10,能在const函數中對mutable變量指派
    } 
}; 

int main()
{
    const Test t;
    
    t.setVal(10);     
    
}                

複制

2)通過const替代後:

class Test{
    
     int * const mval; 
public:
    Test():mval(new int(0)) 
    {
    } 
    void setVal(int num) const 
    {
        *mval=num;             //由于mval是const類型,是以修改時不會報錯
        cout<<*mval<<endl;  //列印20
    } 
}; 

int main()
{
    const Test t;
    t.setVal(20); 
    
}                

複制

3.5 volatile const

大家都知道volatile是指對該變量操作時,不能進行優化

1)在c++中,使用volatile const時,編譯器不會将其放入常數表,而是以隻讀變量的形式來定義

例如:

volatile const int x=1;     
 int *p= (int *)&x;   

 *p=2;
    
 printf("x=%d\r\n",x);           

複制

輸出結果:

x=2           

複制

2) 當使用const時,賦予的值是volatile類型時,也是以隻讀變量形式,因為編譯器不能将該volatile類型的變量優化為一個常量

執行個體:

volatile  int x=1;    
const int y=x;          //y的值是個volatile型

int *p= (int *)&y;
   
*p=2;
    
printf("y=%d\r\n",y);           

複制

輸出結果:

y=2           

複制