C++ CONST 关键词
基础特性
- const定义的变量只有其类型为整型或枚举且以常量表达式初始化才能作为常量表达式的一部分
- const定义常量从汇编的角度看只是给出了对应的内存地址,而不像#define一样给出的 是立即数
- const定义变量在程序运行的过程中只有一份拷贝,而#define定义的常量在内存中有若 干份拷贝
CONST变量默认只在只作用于编译单元内
// file1.cpp
int ext; // or "extern int ext=0;"
// file2.cpp
#include<iostream>
extern int ext;
int main() {
std::cout<<(ext+10)<<std::endl;
}
// output is 10
// file1.cpp
extern int ext; //error, with extern it must be initialized explicitly!
// file2.cpp
#include<iostream>
extern int ext;
int main(){
std::cout<<(ext+10)<<std::endl;
}
//error: In function `main':
//file2.cpp:(.text+0x6): undefined reference to `ext'
//collect2: error: ld returned 1 exit status
// file1.cpp
extern int ext=5; // correct, compared with last example!
// file2.cpp
#include<iostream>
extern int ext;
int main(){
std::cout<<(ext+10)<<std::endl;
}
// output is 15
未被const修饰的变量在不同编译单元的访问
//extern_file1.cpp
extern const int ext=12;
//extern_file2.cpp
#include<iostream>
extern const int ext;
int main(){
std::cout<<ext<<std::endl;
}
const常量在不同编译单元的访问
可以发现未被const修饰的变量不需要extern显式定义也可以在另一个编译单元内用extern关 键字引用,此时可以不初始化,其默认值为零;但是如果显式extern定义则必须对其进行初始 化,否则编译器不知道变量到底在真正哪个文件中定义,会报链接错误!
而const常量则需要显式定义为extern const类型,并且需要做初始化才能在另一个编译单元内用extern const关键字引用该变量!因为常量在定义后就不能被修改,所以定义时必须初始 化,基本用法固定!
定义常量
const int b = 10;
b = 0; // error: assignment of read-only variable ‘b’
const string s = "helloworld";
s[2] = '1' // error: assignment of read-only location of object `s’
const int i,j=0; // error: uninitialized const ‘i’
i 为常量,必须进行初始化!(因为常量在定义后就不能被修改,所以定义时必须初始化。
b 为常量,其值不可更改!
s 为常对象,其映像位置不能被修改!
CONST与指针
const char * a; //指向const变量的指针或者说指向常量的指针
char const * a; //同上
char * const a; //指向变量的const指针。或者说常指针、const指针
const char * const a; //指向const变量的const指针
如果const位于的左侧,则const就是用来修饰指针所指向的变量,即指针所指为常量;
如果const位于的右侧,则const就是修饰指针本身,即指针本身是常量。
指向常量的指针
const int *ptr;
*ptr = 10; //error: assignment of read-only location ‘* ptr’
const int p = 10;
const void * vp = &p;
void *vp = &p; //error: invalid conversion from ‘const void*’ to ‘void*’
const int *ptr;
int val = 3;
ptr = &val; //ok
- 对于指向常量的指针,不能通过指针来修改变量的值
- 不能使用void指针保存const变量的地址,必须使用const void类型的指针保存const 变量的地址
- 允许把非const变量的地址赋值给const对象的指针,如果要修改指针所指向的对象值, 必须通过其他方式修改,不能直接通过当前指针修改
常指针
#include<iostream>
using namespace std;
int main(){
int num=0;
int * const ptr=# //const ptr must be initialized when defined
int * t = #
*t = 1;
cout<<*ptr<<endl;
}
#include<iostream>
using namespace std;
int main(){
const int num=0;
// int * const ptr=# //error: invalid conversion from ‘const int*’ to ‘int*’
cout<<*ptr<<endl;
}
指向常量的常指针
const int p = 3;
const int * const ptr = &p;
理解完前面两种情况,这种情况就比较好理解了
CONST与函数
返回值
const int func1();
const int* func2();
int *const func2();
这些都表明函数返回的变量时某个与const相关的类型。函数返回值赋值变量时,是需要进行一次复制的!
参数
在下面的例子中,外部参数是指拷贝前的实参,内部参数时指拷贝后的实参!
void func(const int var);
void func(int *const var);
由于内部参数本身就不能改变,以上代码的const没有意义
void StringCopy(char *dst, const char *src);
src所指向的区域在函数内不能被修改
void func(const A &a)
避免在传参时进行对象拷贝,同时又防止函数修改参数实例
CONST与类
const成员变量
class Apple{
private:
int people[100];
public:
Apple(int i);
const int apple_number;
};
Apple::Apple(int i):apple_number(i) {}
const成员变量必须通过初始化列表进行初始化
const方法
const对象只能访问const成员函数,而非const对象可以访问任意的成员函数,包括const成员函数