程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> const分別在C和C++語言裡的含義和實現機制

const分別在C和C++語言裡的含義和實現機制

編輯:C++入門知識

const的含義

       簡單地說:const在c語言中表示只讀的變量,而在c++語言中表示常量.

C語言

const是constant的縮寫,是恆定不變的意思,也翻譯為常量,但是很多人都認為被const修飾的值都是常量,其實這是不精確的.因為,精確來說應該是只讀的變量,其值在編譯的時候不能被使用,因為編譯器在編譯的時候不知道其存儲的內容.或許當初這個關鍵字應該被替換為readonly.

C語言中const定義的變量只是給出了對應的內存地址,而不是像#define一樣給出的是立即數,所以,const定義的只讀變量在程序運行過程中只有一個備份(因為它是全局的只讀變量,存放在靜態區),而#define定義的宏變量在內存中有若干個備份.

c++語言:

const是C++中常用的類型修飾符,常類型是指使用類型修飾符const說明的類型,常類型的變量或對象的值是不能被更新的.

         C++引入const的初始目的是為了取代預編譯指令,消除他的缺點,同時繼承它的優點.<缺點:只是簡單值和代碼的替代,缺乏類型的檢測機制,安全性不好;優點有三:1.避免意義模糊的數字出現,清晰程序語義2.方便參數的調整和修改,3.提高程序執行效率,因為不需要為常量分配空間>

問題出來了:為什麼const能取代預定義語句?

1.   首先,以const修飾的變量和對象具有不可變性,這是它能取代預定義語句的基礎.

2.   第二,很明顯,它同樣能避免意義模糊的數字定義,也可以方便地進行參數的調整與修改.

3.   第三,c++編譯器通常不為普通const常量(普通是指內置類型,不包括結構體等類型)分配存儲空間,只是把它們保存在符號表中(注意:c語言中則會為const變量分配存儲空間),這使得它們成為了編譯期間的常量,沒有了存儲和讀內存的操作,使得它的效率非常高,同時,也是它能取代預定義語句的重要基礎.

4.   最後,const定義也能像普通的變量定義一樣,它會由編譯器對它進行類型的安全檢查,消除了預定義語句帶來的安全隱患.

我們使用一張表來總結const的作用:

No.
 作用
 說明
 參考代碼
 
1
 可以定義const常量
  
 const int Max = 100;
 
2
 便於進行類型檢查
 const常量有數據類型,而宏常量沒有數據類型。編譯器可以對前者進行類型安全檢查,而對後者只進行字符替換,沒有類型安全檢查,並且在字符替換時可能會產生意料不到的錯誤
 void f(const int i) { .........}
      //對傳入的參數進行類型檢查,不匹配進行提示
 
3
 可以保護被修飾的東西
 防止意外的修改,增強程序的健壯性。
 void f(const int i) { i=10;//error! }
      //如果在函數體內修改了i,編譯器就會報錯
 
4
 可以很方便地進行參數的調整和修改
 同宏定義一樣,可以做到不變則已,一變都變
  
 
5
 為函數重載提供了一個參考
  
 class A
{
           ......
  void f(int i)       {......} //一個函數
  void f(int i) const {......} //上一個函數的重載
           ......
};
 
6
 可以節省空間,避免不必要的內存分配
 const定義常量從匯編的角度來看,只是給出了對應的內存地址,而不是象#define一樣給出的是立即數,所以,const定義的常量在程序運行過程中只有一份拷貝,而#define定義的常量在內存中有若干個拷貝
 #define PI 3.14159         //常量宏
const doulbe  Pi=3.14159;  //此時並未將Pi放入ROM中
              ......
double i=Pi;   //此時為Pi分配內存,以後不再分配!
double I=PI;  //編譯期間進行宏替換,分配內存
double j=Pi;  //沒有內存分配
double J=PI;  //再進行宏替換,又一次分配內存!
 
7
  提高了效率
 編譯器通常不為普通const常量分配存儲空間,而是將它們保存在符號表中,這使得它成為一個編譯期間的常量,沒有了存儲與讀內存的操作,使得它的效率也很高
  
 

 

const的實現機制

const究竟是如何實現的呢?對於聲明為const的內置類型,例如int,short,long等等,編譯器會如何實現const的本意?那麼對於非內置類型是否也是與內置數據類型一樣處理呢,例如對於結構體類型則會怎樣處理呢?下面通過幾個小例子來說明這些問題:
C語言const示例:


const int i=10;
int *p=(int *)(&i);
*p=20;
printf("i=%d *p=%d \n",i,*p);


猜一猜輸出結果是什麼? i=20 *p=20
C++語言const示例1:


const int i=10;
int *p=const_cast<int *>(&i);
*p=20;

cout<<"i="<<i<<"*p="<<*p<<endl;


輸出結果是 i=10 *p=20
C++語言const示例2:


struct test{
int j;
char tmp;
test()
{
j=30;
tmp='a';
}
};
int main(int argc, char* argv[])
{
const struct test t1;
int *q=(int *)(&t1.j);
*q=40;
cout<<"j="<<t1.j<<"*q="<<*q<<endl;
return 0;
}


輸出結果是 j=40 *q=40

示例結果分析
看到上面三組輸出結果,我們可以分析兩個問題:

問題1:C語言和C++語言中的const究竟表示什麼?

問題2:const的實現機制究竟是怎樣的?

 
問題1,對於const int類型的變量i,C語言中通過指針p修改了值後,i變成了20;而在C++中,通過指針p修改了值後,i仍然是10。
問題2,C++語言中 const struct test的元素j通過指針q被改變了,為何const int 與 const struct test的反應機制不同?

針對問題1,我們知道C語言中const表示只讀的變量,既然把const看成是變量,那麼其在內存中就會有存儲他的空間,並且可以通過指針間接的改變該內存空間的值,當通過指針p改變該內存中的值後,再獲取i的值的時候,會訪問該空間,得到的是被改變後的值。而C++把const看做常量,編譯器會使用常數直接替換掉對i的引用,例如cout<<i; 會理解成cout<<10; 並不會去訪問i的內存地址去取數據,這裡有點像是C語言裡的宏#define i 10。因此C++裡i會輸出10,而*p會輸出20.

針對問題2,C++語言中只是對於內置數據類型做常數替換,而對於像結構體這樣的非內置數據類型則不會。因為結構體類型不是內置數據類型,編譯器不知道如何直接替換,因此必須要訪問內存去取數據,而訪問內存去取數據必然會取到被指針q改變後的值,因此會造成與C++中const int類型完全不一樣的處理模式。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved