從本章起開始從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;
}
複制
輸出結果:
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;
}
複制
輸出結果:
由于指針修改隻讀存儲區的資料,是以導緻程式崩潰
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;
}
複制
輸出結果:
為什麼輸出結果會有兩個不同的值?
這是因為使用&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;
}
複制
輸出結果:
這是因為執行預處理器時,會将遇見到的所有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
複制