C++中const使用的地方非常多,修饰包括:全局变量、函数、函数参数等等,这篇文章主要是总结一下const各种使用的规则以及需要注意事项。
const名叫常量限定符,用来限定特定变量,以通知编译器该变量是不可修改的。习惯性的使用const,可以避免在函数中对某些不应修改的变量造成可能的改动。
C++中const的主要用法大致上可以分为以下几类:
- 修饰基本数据类型
- 应用到函数中
- 在类中用法
- const修饰类对象,定义常量对象
1.const修饰基本数据类型
主要是修饰值变量、reference、pointer
1.1修饰一般常量或则数组
比如:
const int a = 10;
const int arr[3]={1,2,3};
对于类似这些基本数据类型,修饰符const可以用在类型说明符前,也可以用在类型说明符后,其结果是一样的。在使用这些常量的时候,只要不改变这些常量的值便好。
1.2const修饰指针变量*及引用变量&
const修饰指针(*)
这里有一些实际的示例:
int x= 100;
const int* a1 = &x;//[1]
int const * a2 = &x;//[2]
int* const a3 = &x;//[3]
const int* const a = &x;//[4]
《Effective c++》Item21上的总结非常直观明了。
- 如果const位于星号*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;
- 如果const位于星号*的右侧,const就是修饰指针本身,即指针本身是常量。
根据这条规律,[1]和[2]两条中,const位于星号的左侧,所以const含义是修饰变量a1和a2指针指向的内容是常量,也就是不能做 *a1 = 1或则 *a12 = 1这种类似操作,编译器会报错。
[3]为指针本身是常量,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,如a++是错误的.
[4]为指针本身和指向的内容均为常量。
const修饰reference(&)
同样给出一些示例:
int x =100;
int const &a=x;//[1]
const int &a=x;//[2]
int &const a=x;//[3]这种方式定义是C、C++编译器未定义,虽然不会报错,但是该句效果和int &a一样。
对于[1]和[2]这两种定义方式是等价的,此时的引用a的值不能被更新。如:a++ 或则给a赋值这是错误的。
2.const应用到函数中
const在函数中的应用主要有三点:
- 作为参数的const修饰符;
- 作为函数返回值的const修饰符
- 作为函数的const修饰符
不管是作为函数参数的const修饰符还是返回值的修饰符,其实际含义都是一样的。
const修饰函数参数
比如:void fun0(const A* a ); 或则 void fun1(const A& a);
调用函数的时候用相应的变量初始化const常量,则在函数体中,按照const修饰的部分进行常量化。
比如const A* a 则不能对传递进来的指针指向的内容修改,保护原指针所指向的内容;
比如const A& a则不能对传递进来的引用对象的内容修改,保护原引用对象所的内容。
注意:参数const通常用于参数为指针或引用的情况。
const修饰函数返回值
修饰返回值的const,如const A fun2( ); const A* fun3( );
这样声明了返回值后,const按照"修饰原则"进行修饰,保护函数返回的指针指向的内容或则引用的对象不被修改。
const修饰函数
const作用于函数还有一种情况是,在函数定义的最后面加上const修饰,比如:
A fun4() const;
其意义上是不能修改除了函数局部变量以外的所在类的任何变量。
3. 类中定义常量(const特殊用法)
我们要想在类中实现常量定义大致上有几种实现方式
1.使用枚举类型
class test
{
enum {SIZE1=10, SIZE2=20};//枚举常量
int array1[SIZE1];
int array2[SIZE2];
}
2.使用const
不能在类声明中完成初始化const数据成员。 以下用法编译器会报错,因为类对象未被创建时,编译器不知道SIZE的值是什么。
// 错误实例
class test
{
const int SIZE = 100;//编译器报错,企图在类声明中初始化const数据成员
int array[SIZE];//错误,未知SIZE
}
正确使用const用法是:const数据成员的初始化只能在类构造函数的初始化表中进行。
class A
{
A(int size);//构造函数
const int SIZE;
};
A::A(int size) : SIZE(size) // 构造函数的初始化表
{
}
//error 赋值的方式是不行的
A::A(int size)
{
SIZE=size;
}
void main()
{
A a(100); // 对象 a 的SIZE值为100
A b(200); // 对象 b 的SIZE值为200
}
注意:对const成员变量的初始化,不能在变量声明的地方,必须在类的构造函数的初始化列表中完成,即使是在构造函数内部赋值也是不行的。
3.使用static const
通过结合静态变量来实现:
class Year
{
private:
int y;
public:
static int const Inity;
public:
Year()
{
y=Inity;
}
};
int const Year::Inity=1997;//静态变量的赋值方法,注意必须放在类外定义
void main()
{
cout<<Year.Inity<<endl;//注意调用方式,这里是用类名调用的。
}
到这里就把在类中定义常量的方法都陈列出来了。
4.const定义常量对象,以及常量对象的用法
对于不管是标准库中的对象或则是我们自定义的对象,如果我们定义的是const对象,那么对于const对象只能调用const修饰的函数,其余的函数都不能调用。
如下例子:
class test
{
public:
test():x(1)
{
y=2;
}
~test()
{}
void set(int yy)
{
y=yy;
}
int getx() const
{
return x;
}
const int x;
int y;
};
void main()
{
const test t;// 定义的一个const对象
t.set(33);//error,set方法不是const修饰的方法,编译器会报错。
t.getx();
}