最近看完了Stanley B.Lippman的c++ primer,觉得里面有很多知识点涉及到了const,所以就翻了翻原书,找到其中的知识点。
一、const最简单是将对象定义为常量,因为常量在定义后不能修改,所以定义时必须初始化。
const std::string hi = "hello";//可以,初始化成功
const int i,j = 0; //error,i 没有初始化
二、const默认为文件的局部变量,非const变量默认为extern,所以要使const能够在其他的文件中访问,必须显示的指定为extern。如下:
文件file1.cc
extern const int bufferSize = fun();
文件file2.cc
extern const int bufferSize;//注意这里的const对象没有初始化,初始化工作是在文件file1中进行的。
for(int index = 0;index!=bufferSize;++index)
三、const和引用,const引用是指向const的引用
const int ival = 1024;
const int &refVal = ival;
int &ref2 = ival //错误,将一个const指向了非const对象
const 引用可以初始化为不同类型的对象或者初始化为右值,如字面常量
int i = 23;
const int &r = 42;
const int &r2 = i ;
上述三行代码编译器会转换为如下的编码
int temp = i;
const int &r2 = temp
四、指针和const限定符
1、指向const对象的指针,c++强制要求指向const对象的指针也必须具有const特性。
const double *cptr; //cptr是指向double类型的const对象的指针,const限定的是指针指向的对象而非指针本身。
把一个const对象的地址赋给一个普通的非const对象的指针也会导致编译错误:
const double pi = 3.14;
double *ptr = π//错误,ptr是普通指针
const double *cptr = π//正确
不能用void *保存const对象的地址,必须使用const void*保存其地址
const int universe = 42;
const void *cpv = &universe;//OK
void *pv = &universe;//Error
允许把非const对象的地址赋给指向const对象的指针
double dval = 3.14;
cptr = &dval;//但是不能通过cptr改变dval的值
const指针:本身的值亦不能修改
int errNum = 0;
int *const curErr = &errNum;//curErr就是一个const指针,既然是const对象就必须初始化,指针指向对象的属性能不能修改完全取决于该对象自己
指向const对象的const指针
const double pi = 3.14;
const double *const pi_ptr = π//既不能修改pi_ptr也不能修改pi
const既可以放在类型前也可以放在类型后
const int s1;//s1和s2是同一种类型
int const s2;
const对象的动态分配和回收
c++允许创建const对象,如下:
const int *pci = new const int(1024);//如其他常量一样,一经初始化就不能改变。
const对象的删除
delete pci;//即使delete表达式的操作数是指向int型的指针,也照删不误
const形参,
1)void fun(const int i);//则在函数中不能改变实参的局部副本,实参仍以副本的形式传递因此传递给fun的既可以是const对象也可以是非const对象。
2)使用const引用避免复制,在传递大型对象时,需要使用引用形参
bool isShorter(const string &s1,const string &s2){
return s1.size()
} //操作
如果函数具有非const引用形参,则不能通过const进行调用
可基于函数的引用形参是指向const对象还是指向非const对象来实现函数的重载
int lookup(int &);
int lookup(const int &);//重载函数,不能基于指针是否为const来重载函数:
int fun(int *);
int fun(int *const);//这样是错误的
七、将const加在形参列表之后就可以将成员函数生明为常量
int fun() const;//const成员不能改变其操作的对象的数据成员,const必须同时出现在生明和定义中。其中构造函数声明为const是不必要的,不管对象是否为const,都用一个构造函数来初始化对象。
八、this指针中的应用
简单回顾this指针
class Screen{
public:
typedef std::string::size_type index;
Screen& move(index r,index c);
Screen& set(char);
Screen& set(index,index,char);
private:
std::string contents;
index cursor;
index height,width;
};
Screen& Screen::move(index r,index c){
index row = r * width;
cursor = row + c;
return *this;
}
Screen::set(char){
contents[cursor] = c;
return *this;
}
在普通非const成员函数中,this指针式指向类型是const的指针,可以改变this所指向的值,但是不能改变this所保存的地址,在const成员函数中,this指针是指向const类型对象的const指针。既不能改变this所指向的值也不能改变保存this指针的地址。若将display()改成了const,则会出错。
基于成员函数是否为const可以重载一个函数,同样,基于一个指针形参是否指向const可以重载一个函数,const对象只能使用const成员,非const对象可以使用任意成员
class Screen{
public:
Screen& display(std::ostream &os){
do_display(os);
return *this;
}
const Screen& display(std::ostream& os)const{
do_display(os);
return *this;
}
private:
void do_display(std::ostream &os)const{
os<
}
};
九、特殊整形const static成员
一般而言,类的static成员,像普通数据成员一样,不能在类的定义中初始化。相反,类的static成员数据通常在定义时才初始化。
这个规则的一例外就是,是要初始化式是一个常量表达式,整型const static数据成员就可以在类的定义中初始化:
class Account{
public:
static double rate(){return interestRate;}
static void rate(double);
private:
static const int period = 30;
double daily_tbl[period];
};