本文主要说明了const关键字的作用,包括了用于对数组,指针与类相关的修饰方法,作为笔记总结使用。若有错误与不足,欢迎指正。
const关键字
用于修饰一个常类型,常类型的变量或对象的值无法被改变,即无法作为左值,因此在定义时必须进行初始化。
const修饰范围
- 修饰变量与对象,使其成为一般常量与对象常量
- 修饰函数的参数与返回值
- 修饰成员函数的函数体,指类的成员函数
const使用方法
修饰变量与对象
应当注意,除去指针类型,<类型> const与const <类型> 实质都为const <类型>。
但是,例如 int* const 和 const int* 不同,下面会讲解。
- 修饰常用变量
const int a = 2; const double b = 1.23; const bool c;//错误,c需要设定初始值
//int const 与 const int 并无本质区别,实质都是const int
- 修饰引用
const int a = 2; //int &b = a;错误,引用常量时,变量本身也要用const修饰 const int& b = a; b = 3;//错误,const修饰当然不能为左值
- 修饰数组,注意数组中的元素被修饰为const,不能作为左值
const int a[4] = { 1,2,3,4 }; const int b[2][2] = { {1,2},{3,4} }; //int const也一样,以下语句错误,数据元素被修饰为const,不能为左值 a[3] = 1;b[0][0] = 3;
- 修饰指针,
注意指针常量与常量指针的区别
指针常量:不能通过指针来修改变量的值
常量指针:一直指向该变量,不能给该指针赋予其他地址
const <指针类型>
int a = 2;//最好使用const修饰,否则会被修改与目的不符 const int *p1 = &a; //int const *p1=&a也一样 int *p2 = &a; //*p1 = 3;//错误,*p1为指针常量,不能为左值 p1 = p2;//OK,指针本身可以作为左值 a = 4;//虽然无法通过*p1改变值,但可以直接改变a的值,不推荐。
<指针类型> const
int a = 2, b = 3; int* const p1 = &a; int *p2 = &b; p1 = p2;//错误,p1为常量指针,该指针本身不能为左值 *p1 = 3;//OK,指针指向的变量可以为左值
- 修饰指针数组与数组指针
数组指针与指针数组简介
int myarray[4] = { 1,2,3,4 }; int *p1 = 0, *p2 = 0; int* a[2] = { p1,p2 };//a是一个指针数组,数组中元素全部是 int* 类型的指针 int(*b)[4] = &myarray;//b是一个数组指针,b指向一个大小为4的数组 //由于b是一个指向大小为4的数组的指针,首先得到指向的数组:*b,再访问其元素(*b)[pos] cout << (*b)[1] << " " << a[1];
const修饰
int myarray[4] = { 1,2,3,4 }; int *p1 = 0, *p2 = 0; const int* a[2]{ p1,p2 }; *a[0] = 0;//错误,数组中元素为指针常量,其指向的变量不能为左值 a[0] = 0;//OK,指针本身可以作为左值 int* const b[2]{ p1,p2 }; b[0] = 0;//错误,数组中元素为常量指针,指针本身不能为左值 *b[0] = 0;//OK,指针指向的变量可以为左值 const int(*b)[4] = &myarray; b = &myarray;//错误,b本身为一个指向大小为4的数组的指针,被修饰为const,不能作为左值
-
修饰对象与成员变量
class Myclass { public: Myclass(int a,int b) { this->a = a; this->b = b; } int a; int b; }; const Myclass a(1,2); a.a = 2;//错误,被const修饰的对象及其成员变量无法作为左值
注意修饰成员变量时,初始化构造函数必须写在构造函数初始化列表中,而不能写在构造函数体中
class Myclass { public: Myclass(int x, int y)//错误,不能在函数体内初始化 { this->a = x; this->b = a; } Myclass(int x,int y):a(x),b(a){}//OK在构造函数初始化列表中初始化 const int a; const int &b; static const int sc; }; const int Myclass::sc = 2;
- 修饰类中重载函数
class Myclass { public: void print() { cout << "print"; } void print() const { cout << "const print"; } }; const Myclass a; a.print();//const,const对象默认调用const重载函数 Myclass b; b.print();//默认调用非const重载函数
修饰函数的参数与返回值
- 修饰函数参数:被修饰的参数在函数体中生效,不同类型参数的作用在以上都可以找到
若是此处为非指针与引用常量,都在函数中传递实参的副本,无论怎么改变都不会影响实际的值,因此不讨论。
若是此处为指针或是引用常量,都是实参本身传递,需要考虑保护实参本身
//保护实参本身不会被函数体修改 int mymax(const int& a, const int& b) { return a > b ? a : b; } //没有保护 int mymin(int *a, int *b) { return *a > *b ? *b : *a; } int a = 2, b = 3; const int *p1 = &a, *p2 = &b; cout << mymin(p1, p2);//错误,*p1,*p2不能作为左值,而在mymin函数体中可能会被改变
- 修饰函数返回值
const char* getString(); char *str=getString();//错误,getString返回值被修饰为const const char *str=getString();//OK
修饰成员函数的函数体
const放在类成员函数的尾部,用于修饰该成员函数,函数体内不能让类的成员变量作为左值
class Myclass { public: int getval() const { this->val = 2;//错误,不能改变类的成员变量 return this->val; } private: int val; };