const作用
const關(guān)鍵字在C++中真是無處不在,無論是函數(shù)參數(shù),還是函數(shù)返回值,還是函數(shù)末尾都經(jīng)常會(huì)看到const關(guān)鍵字,這表明C++中的const關(guān)鍵字是非常靈活的,
合理地使用const關(guān)鍵字能大大提高我們程序的健壯性。
被const修飾的即表明是常量性的、只讀性的,不可隨意修改的。因?yàn)閏onst對(duì)象一旦創(chuàng)建后其值就不能再改變,所以const對(duì)象必須初始化。
const在C和C++中的區(qū)別
雖然在C中const也表示不可修改的意思,但是它的校驗(yàn)卻沒有C++中那么嚴(yán)格,比如在C中被const修改的變量我們可以通過間接繞過的方式修改,但是在C++中卻是不行的,例如:
main.c
int main() {
const int a = 100;
a = 50; // 編譯錯(cuò)誤
int *p = &a;
*p = 50; // 編譯成功,可以修改a的值
return 0;
}
main.cpp
int main() {
const int a = 100;
a = 50; // 編譯錯(cuò)誤,a的值無法修改
int *p = &a; // 無法編譯通過
const int *p = &a; // 可以編譯通過
*p = 50; // 無法編譯通過,不能通過指針修改a的值
return 0;
}
const到底修飾誰
const在不同的位置修飾的內(nèi)容不一樣,對(duì)于const到底修飾的是誰,誰才是不可變的這個(gè)問題有一個(gè)簡(jiǎn)單的規(guī)則就是const離誰近,誰就不能被修改;。
對(duì)于const修飾的變量從右往左看,const修飾誰就表示誰不可變 (注意const不能修飾)*。也就是const離變量名近就是用來修飾指針變量的,便是這個(gè)變量不可變,離變量名遠(yuǎn)就是用來修飾這個(gè)數(shù)據(jù)的,表示這個(gè)數(shù)據(jù)不可改變。我們通過下面的例子來分析下const到底修飾的是誰:
main.cpp
int main() {
int i = 10;
const int *p1; // const距離int比較近,說明const修飾的是指針p1指向的數(shù)據(jù)不可變
*p1 = 100; // 錯(cuò)誤
int const *p2; // 從右往左看,因?yàn)閏onst不可以修飾星號(hào),所以const修飾的是int,因此這種寫法與p1是一致的
*p2 = 100; // 錯(cuò)誤
int * const p3 = &i; // 這里const距離p3比較近,所以修飾的是p3變量,所以必須初始化
*p3 = 100; // 可以,雖然p3不可以變,但是其指向內(nèi)容是可變的
int j = 20;
p3 = &j; //錯(cuò)誤,p3被const修飾,不可重新指向
const int * const p4 = &i; // 雙重修飾,p4不可變,p4指向的內(nèi)存也不可變
p4 = &j; // 錯(cuò)誤
*p4 = 100; //錯(cuò)誤
return 0;
}
const與函數(shù)之間的那點(diǎn)事
先說下知識(shí)點(diǎn):
1、const可以構(gòu)成函數(shù)重載,如果const構(gòu)成函數(shù)重載,const對(duì)象只能調(diào)用const函數(shù),非const對(duì)象優(yōu)先調(diào)用非const函數(shù)。
2、const放在函數(shù)末端const修飾類的成員函數(shù)表示在本函數(shù)內(nèi)部不會(huì)修改類內(nèi)的數(shù)據(jù)成員,不會(huì)調(diào)用其它非const成員函數(shù)
3、const函數(shù)只能調(diào)用const函數(shù),const對(duì)象,只能調(diào)用const成員函數(shù),非const函數(shù)可以調(diào)用const函數(shù)。
4、const修飾函數(shù)的返回值,如果該函數(shù)是以值的方式返回,則使用const修飾是沒有意義的,如果該函數(shù)返回的是指針,則表示返回的指針的內(nèi)容是不可修改的,需要使用const修飾來接收。
下面是具體的例子:
using namespace std;
class Person{
public:
Person(int a):age(a),name(""){
}
virtual ~Person(){
}
int getAge() const{
name = "hell0"; // 錯(cuò)誤,末端帶const修飾,表示承諾在該函數(shù)內(nèi)不會(huì)改變this對(duì)象的內(nèi)容
std::cout << "getAge const" << std::endl;
return age;
}
int getAge(){
// 與帶const的構(gòu)成函數(shù)重載
std::cout << "getAge" << std::endl;
return age;
}
string getName(){
return name;
}
public:
const int age; // 因?yàn)橛衏onst成員變量的存在,所以這個(gè)變量必須要初始化,所以需要自定義構(gòu)造函數(shù)
string name;
};
void printConst(const Person& person){
std::cout << "printConst" << std::endl;
person.name = "hello"; // 錯(cuò)誤,不可以修改person
}
void print(Person& person){
std::cout << "print const" << std::endl;
person.name = "hello"; // 正確
}
// 這里加的const是沒有價(jià)值的
const Person getPerson1(){
return Person(1);
}
// 返回的指針內(nèi)容不可修改,需要用const接收
const Person* getPerson2(){
return new Person(2);
}
int main() {
Person person1 = getPerson1();
const Person *person2 = getPerson2(); // 因?yàn)間etPerson2的返回值被const修飾,所以返回的指針的內(nèi)容是不可修改的,所以不能去掉const
person1.getAge(); // 調(diào)用不帶const的getAge()
person2->getAge(); // 調(diào)用帶有const的getAge()
print(*person2); // 錯(cuò)誤const對(duì)象只能調(diào)用const函數(shù)
printConst(*person2); // 正確,const對(duì)象只能調(diào)用const函數(shù)
person1.getName(); // 可以
person2->getName(); // 錯(cuò)誤,const對(duì)象只能調(diào)用const函數(shù)
return 0;
}
相信結(jié)合代碼注釋和以上四點(diǎn)知識(shí)點(diǎn)應(yīng)該還是挺好理解的,紙上得來終覺淺,要想真正掌握還是需要實(shí)打?qū)嵉刈约呵们脤?shí)踐一把。
const與mutable
mutable可以說是與const為敵的一個(gè)關(guān)鍵字了,如果使用mutable關(guān)鍵字修飾類的成員變量,那么在那些被const修飾的函數(shù)體內(nèi),也是可以修改這個(gè)成員變量的,例如:
using namespace std;
class Person {
public:
Person(int a) : age(a), name("") {
}
virtual ~Person() {
}
int getAge() const {
name = "hell0"; // 可以,因?yàn)閚ame被mutable修飾了
age = 20; // 不行,age沒有被mutable修飾
std::cout << "getAge const" << std::endl;
return age;
}
public:
const int age; // 因?yàn)橛衏onst成員變量的存在,所以這個(gè)變量必須要初始化,所以需要自定義構(gòu)造函數(shù)
mutable string name;
};
void printConst(const Person &person) {
std::cout << "printConst" << std::endl;
person.name = "hello"; // 可以name被mutable修飾了
}
int main() {
Person person(1);
person.getAge();
printConst(person);
return 0;
}
什么時(shí)候該用const
對(duì)于這個(gè)問題,筆者的意見是不管三七二十一,先把能用const修飾的地方都用上const,等等真正使用這些變量或者函數(shù)提示無法編譯通過的時(shí)候再去詳細(xì)斟酌是需要?jiǎng)h除const修飾呢。還是自己的程序設(shè)計(jì)調(diào)用有問題。
相信很多C/C++都使用過宏,特別是一些C/C++高手更是把宏玩得出神入化,但是如果一個(gè)宏比較復(fù)雜,自己又對(duì)宏的掌握不是那么深入的話,往往會(huì)程序員們產(chǎn)生一些意想不到的困擾,在《Effective C++》一書的第第二和第三條款作者就提倡:
Item 2: 用 const, enums 和 inlines 取代 #defines
Item 3: 只要可能就用 const
關(guān)注我,一起進(jìn)步,人生不止coding?。?!
公粽號(hào):思想覺悟