C/C++中的const
2021-04-17 15:50
856 查看
1 C中的const
C中
const修饰的变量是只读变量,在使用
const关键字声明定义变量时会给该变量分配内存空间。
const修饰的全局变量默认是外部链接的,即其它源文件可以直接使用该变量。
const修饰的局部变量存储在栈区中,不能通过变量名直接修改该变量的值,但是可以通过指针的方式修改该变量对应的值,从某种意义上来说,C中
const修饰的变量不是真正意义上的常量,可以将其当作一种只读变量。
C中const示例:
// fun.c // c中const修饰的全局变量默认是外部链接的 const int num = 100; // a的本质是只读的变量,存放在文字常量区(内存空间只读) // main.c #include <stdio.h> // 对fun.c中的a进行声明(不要赋值) extern const int num; void test() { printf("num = %d\n", num); // num = 200; // error: assignment of read-only variable 'num' } int main(int argc, char *argv[]) { test(); return 0; }
#include <stdio.h> void test() { const int data = 200; // 局部只读变量,通过指针的形式修改data变量的值 printf("data = %d\n", data); // 200 int* p = (int*)&data; *p = 300; printf("data = %d\n", data); // 300 } int main(int argc, char *argv[]) { test(); return 0; }
总结:
-
const
修饰全局变量时,该变量存储在文字常量区(只读),不能通过指针的方式修改其内容 -
const
修饰局部变量是,该变量存储在栈区中(可读可写),通过指针的方式可以修改其内同
2 C++中的const
C++中
const修饰的变量不需要创建内存空间,比如定义常量
const int data = 10;,C++会在一张符号表中添加
name为
data,
value为10的一条记录,如下图所示:
既然,
const修饰的变量没有内存空间,所以在C++中
const修饰的变量才是真正意义上的常量。
C++中定义声明的全局常量是内部链接的,只能作用于当前的整个文件中,如果想让其它源文件对该常量进行访问的,必须加
extern关键字将该常量转换成外部链接。
在C++中,是否为
const常量分配内存空间依赖于如何使用,以下情况会对常量进行内存空间的分配:
- 对
const
常量取地址时 - 使用变量的形式初始化
const
修饰的变量时 const
修饰自定义数据类型(结构体、对象)时
C++中const示例:
// fun.c // const修饰的全局变量,默认时内部链接,不能直接被其它源文件使用 //const int num = 100; // 可以通过将num转换成外部链接的方式,供其它源文件对num的访问 extern const int num = 100; // main.c #include <iostream> using namespace std; extern const int num; struct Person{ int num; char name[32]; }; void test() { cout << "全局num = " << num << endl; // error: undefined reference to `num' // 1. c++中对const修饰的基础类型的变量不会开辟内存空间,只是将其放到符号表中 const int data = 100; // data = 200; // error: 只读 cout << "data = " << data << endl; // 2. 对data取地址时,系统会给data开辟空间 int* p = (int*)&data; *p = 2000; cout << "*p = " << *p << endl; // 2000 cout << "data = " << data << endl; // 100 // 3. 通过变量的形式初始化 const修饰的变量,系统会为其开辟空间 int a = 200; const int b = a; // 系统直接为b开辟空间,不会把b放入到符号表中 p = (int*)&b; *p = 3000; 30ca cout << "*p = " << *p << endl; // 3000 cout << "b = " << b << endl; // 3000 // 4. const修饰自定义类型的变量,系统会分配空间 const Person per = { 100, "viktor" }; // p1.num = 1000; // error cout << "num = " << per.num << ", name = " << per.name << endl; // 100, viktor Person* p1 = (Person*)&per; p1->num = 2000; cout << "num = " << per.num << ", name = " << per.name << endl; // 2000, viktor } int main(int argc, char *argv[]) { test(); return 0; }
总结:
- C++中,使用
const
定义声明变量时,该变量会先放入到符号表中,不会开辟内存空间; const
修饰的全局变量默认是内部链接的;- 对
const
修饰的变量进行取地址操作,系统会对该变量开辟空间; - 使用其它的变量对
const
修饰的变量进行初始化时,系统会对该变量开辟空间; const
修饰自定义的数据类型,系统为自定义数据开辟空间。
3 C/C++中const异同总结
3.1 const修饰全局变量
全局变量存储在只读的文字常量区,所以C/C++中
const修饰的全局变量都不可以更改变量对应的内容。
C中
const修饰的全局变量默认是外部链接的,而C++中默认的是内部链接,如果想使得其变为外部链接可以在
const修饰的全局变量前加
extern关键字。
3.2 const修饰局部变量
const在修饰基础数据类型的局部变量时,在C中会给该变量在栈中开辟内存空间,可以通过指针的方式修改变量的内容;而C++对于
const修饰基础类型的变量是在符号表中添加一条记录,不会在栈中开辟空间,所以不能通过指针的方式修改变量的值。
C++中对
const修饰的局部变量是在如何使用的情况下才分配内存,如果对
const修饰基础数据类型的局部变量进行取地址操作,会对变量分配内存;使用一个变量初始化
const变量时会分配内存;
const修饰的自定义数据类型(结构体、对象)会分配内存。
4 const和#define
在旧版本C中,如果想创建一个常量,必须使用预处理器
#define MAX 1024;。使用宏定义的
MAX对于编译器来说不知其的存在,因为在程序预处理的过程中,所有的
MAX已经被替换为1024,于是
MAX并没有将其加入到符号表中。
如果使用这个常量获得一个编译错误信息时,可能会带来一些困扰,因为这个信息可能会提到1024,但是并没有提到
MAX。
此外
MAX如果被定义在另外一个头文件中,当前可能并不知道1024代表什么,也许解决这个问题要花很长时间。解决办法就是用一个常量替换上面的宏。
const
和#define
的区别:
const
有类型,可进行编译器类型安全检查。#define
无类型,不能进行类型检查
示例:
// 宏没有类型,const有 #define MAX 1024 const short my_max = 1024; void func(short i) { cout << "short函数" << endl; } void func(int i) { cout << "int函数" << endl; } void test() { func(MAX); // int函数 func(my_max); // short函数 }
const
有作用域,而#define
不重视作用域,默认定义出到文件结尾。如果定义在指定作用域下有效的常量,那么#define
就不适用
示例:
// 宏的作用域是当前的整个文件,const的作用域以定义的情况决定 void my_func(void) { // 作用范围是当前复合语句 const int my_num = 10; // 作用范围是当前位置到文件结束 #define MY_NUM 10 } void test() { // cout << "my_num = " << my_num << endl; // err 不识别 cout << "MY_NUM = " << MY_NUM << endl; // ok }
const
可以作为命名空间的成员,而如果将宏作为命名空间的成员,失去了命名空间的意义,因为宏作用于当前的文件,而不是只属于某个命名空间的
5 总结
const由C++采用,并加进标准C中,尽管它们很不一样,在C中,编译器对待
const如同对待变量一样,只不过带有一个特殊的标记,意识是”你不能改变我“。在C++中定义
const时,编译器为它创建空间,所以如果两个不同文件定义多个同名的
const,链接器将发生链接错误。简而言之,
const在C++中用的更好。
在C++中尽量使用
const来替换宏定义,避免不必要的麻烦。
另外在C++中可以使用变量定义数组。对于C,在支持C99标准的编译器中,可以使用变量定义数组。
示例:
#include <iostream> using namespace std; void test() { int a = 10; int arr[a]; int i = 0; for(; i < 10; i++) arr[i] = i; i = 0; for(; i < 10; i++) cout << arr[i] << " "; cout << endl; } int main(int argc, char *argv[]) { test(); return 0; }
相关文章推荐
- C++中的const和C中的区别
- 【C++】const关键字用法总结
- [C++基础]013_神奇的const
- C++中const的用法
- c++前后加const的用途和区别
- C++ const的用法(转)
- 【C++面向对象】C++中成员函数的const属性
- c++——引用、const关键字、动态分配内存、内联函数、函数重载、参数缺省值
- C++ 引用和指针 const与#define #define与内联函数
- C/C++中const关键字详解
- c++ const
- 关于C++ const 的全面总结
- C++标准转换运算符const_cast
- C/C++: const常量与define宏定义的区别
- C++ 之 const 修饰符用法 详解!
- C++中const:常引用,常对象,常对象成员
- C++const成员
- 实例分析C++ 权限控制及const用法
- 【C++札记】const关键字
- 关于C++ const 的全面总结