一文詳解C++中的mutable關鍵字
mutable修飾類的成員變量
以下實例代碼有一個類Person,內部有一個age成員變量表示年齡,有一個被const修飾的公共方法獲取年齡:
#include <iostream> class Person{ public: explicit Person(int a):age(a){ } ~Person(){ } int getAge() const{ return age; } private: int age{18}; }; int main() { const Person person(20); std::cout << "age = " << person.getAge() << std::endl; return 0; }
假如我想擴展一下這個類Person的功能,在其內部增加一個counter的字段,用于統(tǒng)計getAge方法的調用次數(shù),于是將其代碼改成一下這樣子:
#include <iostream> class Person{ public: explicit Person(int a):age(a){ } ~Person(){ } int getAge() const{ counter++; return age; } private: int age{18}; int counter{0}; }; int main() { const Person person(20); std::cout << "age = " << person.getAge() << std::endl; return 0; }
我們發(fā)現(xiàn)代碼無法編譯通過了,因為getAge函數(shù)是被const修飾的,被const修飾的函數(shù),在其內部無法修改該類的成員變量。為了可以讓代碼通過編譯并能順利運行, 于是我們把第10行和第20行的const去掉即可。
這個解決方案可以說是正確的,但是同時也在一定程度傻姑娘破壞了我們設計者的本意,因為程序設計者的本意僅僅是希望counter可以被修改,而age還是不能隨意修改的, 把const刪除后age也可以隨意修改了,同時在《Effective C++》一書中作者也提到過一條準則就是只要可能就用 const
,明顯這個Person也是適合使用const修飾的, 那么我們怎樣修改才能做到既使用const保證其他變量不可隨意修改,又能保證在const函數(shù)體內counter可以修改呢?這時候mutable的關鍵字的作用就體現(xiàn)出來了。
我們僅僅需要在聲明counter變量時使用mutable修飾一下即可,也就是:
class Person{ public: explicit Person(int a):age(a){ } ~Person(){ } int getAge() const{ counter++; return age; } private: int age{18}; mutable int counter{0}; };
同理,如果我們希望在被const修飾的函數(shù)getAge內age變量也可被修改的話,也可以使用mutable修飾age變量。
mutable在Lambda表達式中的作用
C++11標準中引入了 Lambda 表達式,用于定義匿名函數(shù),使得代碼更加靈活簡潔。
我們簡單回顧一下Lambda表達式的語法,Lambda表達式的語法主要分為五個部分,對應為:
[捕獲列表] (函數(shù)參數(shù)) mutable 或 exception 聲明 -> 返回值類型 {函數(shù)體}
其中 mutable 或 exception 聲明
以及返回值類型
是可以忽略不寫的。
捕獲列表的值又可以有以下幾種形式:
包括下面幾種形式:
- [] 表示不捕獲任何變量
- [=] 表示按值傳遞的方法捕獲父作用域的所有變量
- [&] 表示按引用傳遞的方法捕獲父作用域的所有變量
- [=, &a] 表示按值傳遞的方法捕獲父作用域的所有變量,但按引用傳遞的方法捕獲變量a
- [&, a] 表示按引用傳遞的方法捕獲父作用域的所有變量,但按值傳遞的方法捕獲變量a
其中按值捕獲[=]
的方式不允許程序員在 Lambda 函數(shù)的函數(shù)體中修改捕獲的變量。而以 mutable 修飾 Lambda 函數(shù),則可以打破這種限制。
例如一下代碼是無法編譯通過的:
#include <iostream> int main() { int x{0} ; auto f1 = [=]() {return ++x;}; f1(); std::cout << "x = " << x << std::endl; return 0; }
因為Lambda表達式f1,在內部修改了表達式外部x的值,但是又沒有使用mutable關鍵字聲明,此時我們只需要使用mutable關鍵字聲明一下f1即可:
#include <iostream> int main() { int x{0} ; auto f1 = [=]() mutable {return ++x;}; f1(); std::cout << "x = " << x << std::endl; return 0; }
在這里考考大家一個簡單的問題,為什么在f1內部改變了外部x的值,但是打印x的值還是0呢?為何沒有生效呢?
針對以上例子如果想要在表達式外部修改x的值,筆者覺得直接在捕獲列表中使用引用傳遞不是更加方便明了嗎,mutable關鍵字在Lambda表達式中是否有點脫褲子放屁的感覺?
以上就是一文詳解C++中的mutable關鍵字的詳細內容,更多關于C++ mutable關鍵字的資料請關注腳本之家其它相關文章!