C++
基本功:全面掌握
const
、
volatile
和
mutable
關鍵字
???? C++
程式設計過程中
,const
的使用可以頻度是非常高的
.
它在保證程式安全方面起到了不可估量的作用
.
用一句話來表達最確切不過了:”小兵立大功”
.
??
有了
const,
那么
mutable
當然缺不了
.
??
然作為
const
的同胞兄弟
,volatile
卻在很多人的視野中消失
.
其實
volatile
擔負的責任有何嘗小呢
?
??
自然
,
它們的用法多樣而靈巧
,
以至新手迷惑久久
,
下面就來系統的探討總結一下吧:
一
.
一般應用
1.const
修飾各種變量的用法
.
?? a.
取代
define
???? #define D_INT 100
???? #define D_LONG 100.29
???? ………
???? const int D_INT = 100;
???? const D_INT = 100;???? //
如果定義的
int
類型
,
可省略
int.
???? const long D_LONG = 100.29;
???? ………
???? const int& a = 100;
???? const
替代
define
雖然增加分配空間
,
可它卻保證了類型安全
.
????
在
C
標準中
,const
定義的數據相當于全局的
,
而
C++
中視聲明的位置而定
.
?? b.
修飾指針相關的變量
????
以三組簡單的定義示意:
???? Group1:??
???? int a = 0;???
???? const int* b = &a;------------? [1]???????????????
???? int const *b = &a;------------? [2]????????????????????
???? const int* const b = &a;---- [4]??
?????????
???? Group2:?
???? const char *p = "const";--------------[1]
???? char const *p = "const";--------------[2]??
???? char* const p = "const";--------------[3]??
???? const char * const p = "const";----[4]?????
????
???? Group3:
????? int a=0;
??????? const int &b = a;---------------[1]
???? int const &b = a;---------------[2]?
???? int & const b = a;--------------[3]? //--->
修飾引用時
,const
被忽略
???? const int & const b = a;-----[4]
????
總結:
???? 1.
如果
const
位于星號左側
,
則
const
用來修飾指針所指向的變量
,
??????
即指針指向的為不可變的
.
???? 2.
如果
const
位于星號右側
,const
就是修飾指針本身
,
即指針本身是
??????
不可變的
.
??????
因此
,[1]
和
[2]
的情況相同
,
指針所指向內容不可變
(const
放在變量
??????
聲明符的位置無關
),
??????
這種情況下不允許對內容進行更改
,
如不能
*a = 3 ;
???? 3.[3]
中指針本身是不可變的,而指針所指向的內容是可變的
,
這種情況
??????
下不能對指針本身
??????
進行更改操作
,
如
a++
是錯誤的
???? 4.[4]
中指針本身和指向的內容均為常量
.(
引用特殊:引用在使用增加
??????
遇義時
,
增加它代表的變量
.
所以
qualifiers on reference are ignoredv.
??????
延伸點
:
??????
注意示例
:
?????? 1.const int& reference = 1000;
?????? 2.char* p = "const"
???????? char*& q ;
??
2.const
在函數環境下的各種應用
??
常用法示例如下:
?? const A&? _Fun(const? A& _in);? //
修飾引用型傳入參數
?? // A? _Fun(const A& _in);
?? //A& _Fun(const A& _in);
?? //
上面的兩種
,
在函數內部有特殊的步驟
,
這里不詳提了…
..
?
?? const? A*? _Fun( const? A* _in);?? //
修飾指針型傳入參數
?? void _Fun( ) const;?? //
修飾
class
成員函數
?? const? A&? _Fun(A& _in );? //
修飾返回值
?? const A & operator(const A& _in);? //
同時修飾傳入參數和返回值
?? a.
修飾參數
????
如
void _Fun(const A* _in)
或
void _Fun(const A& _in);
????
它們被修飾后
,
在函數執行期間行為特性同于上面的講解
,
????
注意:這不會改變原來數據的是否是
const
的屬性
.
?? b.
修飾函數返回值
??? const A&? _Fun( )
??? const A*?? _Fun( );
???
注意:由于生命期不同步的問題
,
不可將局部的變量的指針或引用返回
(static
除外
).
???
另外
,
傳出來的視情況
,
代表不同的意思…
???
對于
A&
返回類型
,
你若將之賦與其它變量
,
那么它實際執行的是將返回的變量
??? (
或引用
)
代表的數據賦出
..
而你若將其它值賦予之
,
那么被賦予的是變量或引
???
用代表的數據
.
而
const A&
一般是防止之做為左值被賦值
.
???
這個地方還有很多的細節問題
(
譬如在連續賦值、返回的臨時對象的處理、
???
重載的
const
和非
cosnt
運算符等等
),
讀者自己在實踐中需要多多總結
.
二、難點
3.
修飾類成員函數的
const.
??
形如
:void _Fun() const { };
??
你需要知道的幾點規則:
?? a.const
對象只能訪問
const
成員函數
,
而非
const
對象可以訪問任意
????
的成員函數
,
包括
const
成員函數
.
?? b.const
對象的成員是不可修改的
,
然而
const
對象通過指針維護的對象卻
????
是可以修改的
.
?? c.const
成員函數不可以修改對象的數據
,
不管對象是否具有
const
性質
.
它在
????
編譯時
,
以是否修改成員數據為依據
,
進行檢查
.
?? e.
然而加上
mutable
修飾符的數據成員
,
對于任何情況下通過任何手段
????
都可修改
,
自然此時的
const
成員函數是可以修改它的…
4.
談談
volatile
和”完全
const
對象”
?
一個有
volatile
修飾的類只允許訪問其接口的一個子集,這個子集由類的
?
實現者來控制
.
用戶只有用
const_cast
才可以訪問這個類型的全部接口
.
而且
,
?
象
const
一樣,類的
volatile
屬性會傳遞給它的成員
.
想象
const
修飾的對
?
象
,
它的成員變量是不可修改的
,
而它通過指針維護的對象或原生變量是可
?
修改
.
那么我們想
:
如果對象維護一個
char* ,
則它相當于
char*
? const chrptr ;
而不是
const char* cosnt chrptr;
對于類中的指針你需要
?
這樣修飾以防止它或它維護的資源:
cosnt x* xptr;
而不是
x*const xptr;
?
因為
cosnt
修飾的對象它默認
的行為是延續變量:
x* cosnt xptr;
?
更重要的
,volatile
修飾的數據
,
編譯器不可對其進行執行期寄存于寄存器的優化
.
?
這種特性
,
是為了多線程同步的需要
.
有興趣者看參看
Andrei
的
GP
系列文章
.
5.
談談
const_cast
轉換運算符
?
這個關鍵字最基礎的用法是:去掉數據的
const
性質
.
?
值得注意的是:它只對指針、引用和其它的具有指向性質的類型
.
參考:
??? 1.
《
Effective C++
》關于
const
兩種語義的論述
??? 2.Andrei Alexandrescu
《
volatile
——編寫多線程程序的好幫手》