设为首页 加入收藏

TOP

68.C++中的const(一)
2023-07-23 13:35:42 】 浏览:111
Tags:68.C const

??编写程序过程中,我们有时不希望改变某个变量的值。此时就可以使用关键字 const 对变量的类型加以限定。

初始化和const

??因为const对象一旦创建后其值就不能再改变,所以const对象必须初始化。一如既往,初始值可以是任意复杂的表达式:

const int i = get_size();//正确:运行时初始化
const int j = 42;//正确:编译时初始化
const int k;//错误:k是一个未经初始化的常量 

??正如之前反复提到的,对象的类型决定了其上的操作。与非const类型所能参与的操作相比,const类型的对象能完成其中大部分,但也不是所有的操作都适合。主要的限制就是只能在const类型的对象上执行不改变其内容的操作。例如,const int和普通的int一样都能参与算术运算,也都能转换成一个布尔值,等等 。
在不改变const对象的操作中还有一种是初始化,如果利用一个对象去初始化另外 一个对象,则它们是不是const都无关紧要:

int i = 42;
const int ci = i;//正确: 1的值被拷贝给了ci
int j = ci;//正确:ci的值被拷贝给了J

默认状态下,const对象仅在文件内有效

const修饰变量是也与static有一样的隐藏作用。只能在该文件中使用,其他文件不可以引用声明使用。 因此在头文件中声明const变量是没问题的,因为即使被多个文件包含,链接性都是内部的,不会出现符号冲突。

??当以编译时初始化的方式定义一个const对象时,就如对bufSize的定义一样:

const int bufSize = 512;//输入缓冲区大小

??编译器将在编译过程中把用到该变量的地方都替换成对应的值。也就是说,编译器会找到代码中所有用到bufSize的地方,然后用512替换。为了执行上述替换,编译器必须知道变量的初始值 。如果程序包含多个文件,则每个用了const对象的文件都必须得能访问到它的初始值才行。要做到这一点,就必须在每一个用到变量的文件中都有对它的定义(参见C++Primer 2.2.2节,第41页)。为了支持这一用法, 同时避免对同一变量的重复定义,默认情况下,const对象被设定为仅在文件内有效。当多个文件中出现了同名的const变量时,其实等同于在不同文件中分别定义了独立的变量。
??某些时候有这样一种const变量,它的初始值不是一个常量表达式,但又确实有必要在文件间共享。这种情况下,我们不希望编译器为每个文件分别生成独立的变量。相反,我们想让这类const对象像其他(非常量)对象一样工作,也就是说,只在一个文件中 定义const,而在其他多个文件中声明并使用它。
??解决的办法是,对于const变量不管是声明还是定义都添加extern关键字,这样只需定义一次就可以了:

//file_l.c定义并初始化了一个常量,该常量能被其他文件访问
extern const int bufSize =fen();
//file_l.h头文件
extern const int bufSize;//与file_l.c中定义的bufSize是同一个
假设我们有两个文件:main.cpp和helper.cpp。我们在main.cpp中定义了一个全局变量,并使用const关键字进行修饰:
```cpp
// main.cpp
const int MAX_VALUE = 100;
int main() 
{
    // 使用MAX_VALUE
    return 0;
}
```
然后我们在helper.cpp中尝试引用这个变量:
```cpp
// helper.cpp
extern const int MAX_VALUE;
void helperFunction()
{
    // 使用MAX_VALUE
}
```
这时候编译器会报错,提示MAX_VALUE未定义。这是因为const修饰的变量默认具有内部链接(internal linkage),只能在当前文件中使用,其他文件无法访问。因此,我们需要在helper.cpp中重新定义MAX_VALUE:

```cpp
// helper.cpp
const int MAX_VALUE = 100;
void helperFunction() 
{
    // 使用MAX_VALUE
}
```
这样就可以在helper.cpp中使用MAX_VALUE了。注意,这里重新定义的MAX_VALUE和main.cpp中定义的MAX_VALUE虽然名字相同,但是它们是两个不同的变量,它们的地址也不同。
const修饰变量的隐藏作用是只能在该文件中使用,其他文件无法引用声明使用。如果想在其他文件中使用这个const修饰的变量,可以通过将该变量的定义放在头文件中,然后在其他文件中包含该头文件来实现。

下面是一个例子:
// header.h
#ifndef HEADER_H
#define HEADER_H
const int MAX_VALUE = 100;
#endif // HEADER_H

// file1.cpp
#include "header.h"
int main() 
{
    const int value = MAX_VALUE;
    // ...
}

// file2.cpp
#include "header.h"
int main() 
{
    int value = MAX_VALUE;
    // ...
}

1.变量中的const

1.1 普通变量

直接在普通变量类型声明符前加上const,可以将其声明为const类型:

const int a = 0;

这样就把a声明成了一个const类型的常量,所以我们不能再改变它的值了,所以下面试图改变a的语句将会编译报错:

a = 10;

修改局部变量的值:

1.如果const修饰的局部变量是基础的类型(int char double等等),并且初始化使用字面常量的话,不会给该变量分配空间。
例如:

void test()
{
	const int a = 10;//用字面常量10来初始化
	a = 20;//error
}

2.但是,当我们对这个变量进行取地址的操作的时候,系统会为该变量分配空间。

void test() 
{
	const int a = 10;
	//a = 20;//error
	int* p = (int*)&a;
	*p = 20;
	cout << a << endl;
	cout << *p << endl;
}

上面的结果是:10和20

??这是因为,当我们定义一个被const修饰并且使用字面常量来初始化的局部变量的时候,系统会把这个变量看作是一个符号,放入到符号表中,这么变量名就是一个符号,值就是这个符号的值,类似于#define的作用。(这就是 C++ 中的常量折叠 ,因为常量是在运行时初始化的,编译器对常量进行优化,直接将常量值放在编译器的符号表中,使用常量时直接从符号表中取出常量的值,省去了访存这一步骤。)

??当我们对这个变量取地址的时候,由于原来没有空间,就没有地址,现在需要取地址,所以才被迫分配一块空间,我们通过地址的解引用可以修改这个空间的值,这也就是为什么第二个结果为20的原因,但是如果我们还是通过变量名来访问数据的话,系统会认为这还是一个符号,直

首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Leetcode Practice -- 数组 下一篇C++/Qt网络通讯模块设计与实现(三)

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目