const限定符的一些使用区别
const限定符的一些使用区别
注意事项
const对象必须初始化
const对象仅在文件内有效,多个文件同名的const变量,实际上是在不同文件里分别定义了独立的变量。
在头文件中声明的const对象,与宏定义#define是一样的用法,只要包含该头文件,就可以直接使用该对象
需要注意的是,如果实现文件里重新定义了一个同名文件,那么该块内重新定义的对象有效,如下:
//test.h
const int a = 5;
//main.cpp
#include <iostream>
using namespace std;
int main()
{
cout << a << endl;
int a = 6;
a = 7;
cout << a << endl;
}
输出结果是5和7,第一个打印的是头文件中的 a 的值,因为在预编译的时候已经把该声明编译到该文件中了,第二个打印的是重新声明的变量 a 的值。
如果想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字, 如下:
//test.cpp
extern const int b = 8;
//main.cpp
#include <iostream>
extern const int b;
using namespace std;
int main()
{
cout << a << endl;
int a = 6;
a = 7;
cout << a << endl;
cout << b << ensl;
}
b的输出结果是8,需要注意的是:
//main.cpp
#include <iostream>
extern int b;
如上述这样声明程序不会报错,同样可以输出b的值8。但是,由于没有const限定符,编译器会允许对b进行赋值,一旦对b进行了赋值,编译器不报错,但运行时程序会崩溃。
引用
有下面这样一种情况,我们声明了一个变量,这个变量随着程序运行是会发生变化的,我们在另一个地方希望使用这个值,但是不能改变这个值,就可以创建一个这个变量的常量引用
double dVal = 3.14;
const double &ri = dVal;
这样,dVal的值变化时,ri跟着变化,但是不允许对ri进行赋值;
double dVal = 3.14;
const int &ri = dVal;
上面这样也可以,但会产生一个临时变量来进行类型转换
const int temp = dVal;
const int &ri = temp;
只是,发生类型转换时,必须声明的是一个常量引用,如果是下面这样
double dVal = 3.14;
int &ri = dVal;
编译器就会报错,因为这种发生了类型转换的引用,实际上是把引用绑定在了临时变量上,c++语言是不允许的。
指针
指向常量的指针(指针常量)
这种情况与引用的用法是一样的,指向常量的指针也没有规定其所指的对象必须是一个常量。所以指向常量的指针仅仅要求不能通过该指针改变对象的值,而没有规定那个对象的值不呢个通过其他途径改变。
// 1
double pi = 3.14;
double *ptr = π //正确
// 2
const double pi = 3.14;
double *ptr = π //错误,必须定义成指针常量,同样,引用也是如此
// 3
const double pi = 3.14;
const double *ptr = π //正确,指针常量
第1种情况,可以通过指针进行赋值操作如:
*ptr = 6.66; //正确,同时pi的值也被改变
但是第三种情况就不能进行赋值,也就是说定义一个指针常量,指向的内存空间中要放一个常量,可以通过指针来调用这个值,却不能改变它,如果改成如下,更直观些:
// 4
double pi = 3.14;
const double *ptr = π //正确
第3种情况中,我们声明了一个常量,那么再声明一个指针时,就只能声明一个指针常量。如第4种情况,pi的值可以改变,取值 *p时,值同样会跟着改变,但是不能对 *p进行赋值。
另外,将const double 写成double const也可以,两者等价,仅是书写风格问题,不再讨论。
另一种情况就是const指针(常量指针)
指针是对象而引用不是,因此就像其他对象类型一样允许把指针本身定义为常量。常量指针必须初始化,而一旦初始化完成,则他的值就不能再变了。我们拿第1种情况改一下举例:
// 5
double pi = 3.14;
double *ptr = π //正确
cout << *ptr << endl;
double dVal2 = 9.999;
ptr = &dVal2; //正确
cout << *ptr << endl;
一般的指针是可以重复赋值的,也就是一个变量,但是加上const就会发生改变:
// 6
double pi = 3.14;
double *const ptr = π //正确
cout << *ptr << endl;
double dVal2 = 9.999;
ptr = &dVal2; //错误, 指针不能被改变
cout << *ptr << endl;
声明函数
在函数声明中的用法是一样的
const int fun1(int *ptr); //返回值应该是一个常量而不是变量,通常返回的值都是常量,
//两种常见的返回非const对象情形是,重载赋值运算符以及重载与cout一起使用的<<运算符。不过多讨论
int fun2(const int *ptr); //传递一个参数进来,但是在这个函数内,该参数不能被改变
另外会看到类似如下这样的函数
void func2()const; //通常不能这样声明函数
这是在类中才能这样声明,意思是这个成员函数里,不能改变成员变量;
class val
{
int m;
public:
void fun3()const; //正确
};
void val::fun3()const
{
m = 3; //报错,m 是成员变量,这里不能被改变
}
下一篇: sudo-为普通用户提权