const与指针结合使用时,容易让人迷惑的是:
1. const到底是限定该指针不可再指向其它内存呢?
2. 还是禁止通过该指针修改其指向的内存块的内容?(PS:这里说的是禁止通过该指针修改内存块,所以不是不能修改,而是要通过其它方式去修改。)
下面来探究一下,先上基础代码。
// Box.h author:sodino@qq.com
#ifndef _BOX_H
#define _BOX_H
class Box {
public :
Box();
int volume();
void print() const ;
void setLength(int) const;
void setWidth(int);
~Box();
private :
mutable int length; // mutable:可在const函数中修改
int width;
int height;
};
#endif
// Box.cpp
#include <iostream>
#include "Box.h"
using namespace std;
Box::Box(){
length = width = height = 0;
cout << "Box " << this << " constructor() executed." << endl;
}
Box::~Box() {
cout << "Box " << this << " deconstructor() executed." << endl;
}
void Box::setLength(int l) const{
length = l;
}
void Box::setWidth(int w){
width = w;
}
int Box::volume(){
return length * width * height;
}
void Box::print() const {
cout << "len=" << length << " width=" << width << " height=" << height << endl;
}
以上基础代码。现在来研究一下:
Box * const p
Box const * p
const Box * p
这三者的区别。
Box * const p
Box box, bOther; // 这里不需要new即已经初始化了
box.print();
Box * const p1 = &box;
p1 = &bOther; //error: read-only variable is not assignable
代码如上时,根据“error: read-only variable is not assignable”的提示,可以确定const修饰的是其左边的指针,意义为在该指针p1初始化后,禁止再“移情别恋”指向其它地址。
Box const * p
Box box, bOther; // 这里不需要new即已经初始化了
box.print();
Box const * p1 = &box;
p1 = &bOther; // 可以重新指向一个新地址
p1->setLength(20); // const修饰的函数,仅可修改mutable的成员变量
p1->setWidth(20); // error: member function 'setWidth' not viable:
// 'this' argument has type 'const Box', but function is not marked const
代码如上时,发现p1是可以再重新赋值,指向其它内存地址的。但当调用Box的非const函数时,则会提示error。所以确定const修饰意义是禁止通过p1指针修改其指向的内存块的内容。
const Box * p
Box box, bOther; // 这里不需要new即已经初始化了
box.print();
const Box * p1 = &box;
p1 = &bOther; // 可以重新指向一个新地址
p1->setLength(20); // const修饰的函数,仅可修改mutable的成员变量
p1->setWidth(20); // error: member function 'setWidth' not viable:
// 'this' argument has type 'const Box', but function is not marked const
代码如上时,和Box const * p的情形是一致的。
最后,如果是const Box * const p,则即是禁止了指针p指向其它地址,也禁止通过指针p修改其指向的内存块的内容。
总结:
联想到const对成员函数的修饰格式为:
void Box::setLength(int l) const{ // const放在最末
length = l;
}
const是放在最末的,当const放在函数前头时则是无效的,所以认定为const修饰符对其左边的内容起修饰作用;但当const本身就是最左边的修饰符,那么会对右边的东西起作用。