1. 程式人生 > >Effective C++筆記之三:儘可能使用const

Effective C++筆記之三:儘可能使用const

一.const作用於迭代器
       STL選代器系以指標為根據塑模出來,所以迭代器的作用就像個T*指標。宣告選代器為const就像宣告指標為const一樣(即宣告一個T* const 指標) ,表示這個迭代器不得指向不同的東西,但它所指的東西的值是可以改動的。如果你希望迭代器所指的東西不可被改動(即希望STL模擬一個const T* 指標) ,你需要
的是const_iterator:
std::vector<int> vec;
.....
const std::vector<int>::iterator iter = vec.begin( );
*iter = 10;// OK
++iter;// error
std::vector<int>::const_iterator cIter = vec.begin( );
*cIter = 10;// error
++cIter;// ok
二.const作用於自定義型別的物件
       在定義物件時指定物件為常物件。常物件中的資料成員為常變數,例如:
#include <iostream>
using namespace std;
 
class Time
{
public:
    void printf() const
    {
       //h = 10;//error C3490: 由於正在通過常量物件訪問“h”,因此無法對其進行修改
       m = 10;// ok
       cout << "Hour:" << h << "Minute:" << m << "Second:" << s << endl;
    }
 
    void show()// 不會導致編譯錯誤
    {
       h = 10;
    }    
private:
    int h;
    mutable int m;
    int s;
};
 
int main()
{
    const Time t;
    t.printf();
    system("pause");
    return 0;
}
       

       常物件t中的資料成員雖然未顯示定義為const資料成員,但它們都是常變數,無法修改它們的值。

       常成員函式printf可以訪問常物件中的資料成員,但是不允許修改常物件中的資料成員,除非該資料成員被宣告為mutable。
       普通成員函式show雖然不會導致編譯錯誤,但是無法被常物件呼叫,因為常物件、指向常物件的指標或引用只能用於呼叫其const型成員函式,而不能呼叫其非const型的成員函式。
三.const作用於函式
1.令函式返回一個常量值
       這樣做往往可以降低因客戶錯誤而造成的意外,而又不至於放棄安全性和高效性,例如,考慮有理數(rational numbers)的operator*宣告:
class Rational{ ... };
const Rational operator* (const Rational& lhs, const Rational& rhs);
       這個宣告能很好的杜絕由於筆誤而導致的如下操作:
Rational a,b,c;
if(a * b = c)
{
   ......
}
       如果a和b都是內建型別,這樣的程式碼直截了當就是不合法。而一個"良好的使用者自定義型別"的特徵是它們避免無端地與內建型別不相容。
2.const引數
       至於const引數,沒有什麼特別新穎的觀念,它們不過就像local const物件一樣,你應該在必要使用它們的時候使用它們。除非你有需要改動引數或local物件,否則請將它們宣告為const。只不過多打6個字元,卻可以省下惱人的錯誤,像是"想要鍵入'=='卻意外來鍵成'=的錯誤,一如稍早所述。
四.const資料成員
       常資料成員的值是不能改變的,且必須初始化,因為常資料成員是不能被賦值的,關於初始化,詳見:Effective C++筆記之一:宣告、定義、初始化與賦值

#include <iostream>
using namespace std;
 
class Time
{
public:
   void printf() const
   {
       //h = 10;//error C3490: 由於正在通過常量物件訪問“h”,因此無法對其進行修改
       m = 10;
       cout << "Hour:" << h << "Minute:" << m << "Second:" << s << endl;
   }
 
   //void show()// C2166: 左值指定const物件
   //{
   //    h = 10;
   //}    
private:
   //const int h;// 報錯,沒有初始化
   const int  h = 10;// 初始化
   mutable int m;
   const int s = 10;// 初始化
};
 
int main()
{
   const Time t;
   t.printf();
   system("pause");
   return 0;
}
      

       對比“二.const作用於自定義型別的物件”小節,可看出const物件中const資料成員和非const資料成員的區別。

五.const成員函式
       常成員函式只能引用本類中的資料成員(const和非const),而不能修改他們。
       const是函式型別的一部分,在宣告函式和定義函式時都要有const關鍵字,在呼叫時不必加const。const員函式可以引用const資料成員,也可以引用非const資料成員。const資料成員可以被const成員函式引用,也可以被非const資料成員函式引用,但是不能被修改。
需要注意的是:
1.不要誤認為常物件中的成員函式都是常成員函式。常物件只能保證所有的資料成員的值不被修改。如果在物件中的成員函式為加const宣告,編譯系統把它作為非const成員函式處理。
2.兩個成員函式如果只是常量性(constness)不同,可以被過載。舉個例子
#include <iostream>
using namespace std;
 
class TextBlock
{
public:
   TextBlock::TextBlock(string str) :test(str)
   {
    
   }
   const char & operator[](size_t position) const
   {
    return test[position];
   }
   char & operator[](size_t position) 
   {
    return test[position];
   }
private:
    string test;
};
 
int main()
{
   TextBlock tb("Hello");
   cout << tb[0] << endl;
   const TextBlock ctb("World");
   cout << ctb[0] << endl;
 
   system("pause");
   return 0;
}


3.常成員函式不能呼叫另一個非const成員函式。但是非const成員函式可以呼叫const成員函式。舉個例子:

在上述例子中,過載的兩個操作符函式體內的程式碼量小,感覺不到有什麼不妥。但是如果程式碼量大的話,可以讓非const operator[]呼叫其const兄弟來避免程式碼重複。
#include <iostream>
using namespace std;
 
class TextBlock
{
public:
   TextBlock::TextBlock(string str) :test(str)
   {
    
   }
   const char & operator[](size_t position) const
   {
    return test[position];
   }
   char & operator[](size_t position) // 先呼叫const版本的操作符,然後去掉返回結果的const屬性
   {
    return
        const_cast<char&>(
        static_cast<const TextBlock&>(*this)[position]);
   }
private:
    string test;
};
 
int main()
{
   TextBlock tb("Hello");
   cout << tb[0] << endl;
   const TextBlock ctb("World");
   cout << ctb[0] << endl;
 
   system("pause");
   return 0;
}
六.指向物件的常指標
       將指向物件的指標變數宣告為const型並將之初始化,這樣指標值始終保持為其初始值,不能改變,即其指向始終不變。如:
int a = 1 , b;
int * const ptr1 = &a;
ptr1 = &b;// error C3892: “ptr1”: 不能給常量賦值
       指向物件的常指標的值不能改變,即始終指向同一個物件,但可以改變其所指向物件(如b)中資料成員的值。
七.指向常物件的指標
1.如果一個變數已經被宣告為常變數,只能用指向常變數的指標指向它,而不能用一般的(指向那個非const型變數的)指標變數去指向它。
2.指向常變數的指標除了可以指向常變數,還可以指向非const變數。此時不能通過指標變數改變該變數的值。
3.指向常物件的指標常作為函式引數。

八.物件的常引用
       在C++面向物件程式設計中,經常用常指標和常引用作函式引數。這樣既能保證資料安全,使資料不能被隨意修改,在呼叫函式時又不必建立實參的拷貝。
--------------------- 
作者:燦哥哥 
來源:CSDN 
原文:https://blog.csdn.net/caoshangpa/article/details/79437030?utm_source=copy 
版權宣告:本文為博主原創文章,轉載請附上博文連結!