我们如何修改常量变量的值


">

完整参考C++"的第四版写道:">const类型的变量可以被程序外部的东西修改。例如,硬件设备可以设置其值。

这意味着什么,以及如何实现。

有两种方法可以考虑const的含义,或者另一种方式,即当您使用const限定符告诉编译器有关代码的一些信息时,的意思。

定义一是,"这个变量永远不会改变,所以它应该放在只读内存中。

但定义二是,"我不打算让我的代码(或任何其他代码)修改这个变量,所以如果我不小心尝试修改,请警告我。

那么问题来了,如果你(意外或其他)尝试更改const变量的值会发生什么? 然后你问的问题,你会怎么尝试?

如果const变量实际上已被放置在只读内存中,那么如果您尝试修改它,会发生什么情况,您将获得某种分段错误或总线错误。 但是,如果它不在只读内存中(如果定义编号 2 有效),并且如果您尝试修改 const 变量,则会成功。

那么另一个问题:它如何改变? 有很多可能性。

一种方法是作弊。 如果你写类似的东西

const int i = 5;
int *ip = (int *)&i;
*ip = 6;
printf("%dn", i);

您很有可能成功将i更改为 6。 这是未定义的行为,不能保证有效 - 您绝对不应该将指针指向const的东西,使用显式强制转换来清除恒常性,并使用生成的指针尝试更改值。 所以它可能不起作用 - 或者它可能。

另一种方法是在const背后做点什么。 假设您编写以下代码:

int j = 5;
const int *ip2 = &j;
printf("%dn", *ip2);
j = 6;
printf("%dn", *ip2);

在这种情况下,const的是指针ip2指向的内容。 在这里,定义 2 绝对适用:我们承诺做的只是不修改ip2指向的内容。 (但在这种情况下,const限定符不会导致将任何内容放入只读内存,因为ip2可以指向任何位置。 第二段代码没有错;甚至没有明确的演员阵容,更不用说粗略或非法的演员了。 如果我们试图说编译器会(正确地)抱怨*ip2 = 6,但在这种情况下,没有什么可以阻止我们(或其他一些代码片段)更改j,但这确实意味着 - 惊喜,惊喜 -*ip2背后的价值可以改变。

另一种可能性(尽管这又有点粗略)是全局变量在一个文件中声明为const,而在另一个文件中声明为non-const。 如果在文件 1 中我们有

整数 g = 5;

在文件 2 中,我们有

extern const int g;

在文件 1 中,我们将g从 5 更改为 6,然后在文件 2 中,当我们认为g是恒定的时,我们可能会惊讶地看到这种变化。

最后,我能想到的最后一种可能性是相当奇怪的声明

const volatile int x;

变量既constvolatile是什么意思? 好吧,const意味着此代码无法更改它,但volatile意味着它可能因其他原因而更改。 这将是描述只读机器寄存器的一种方法。 这大概就是这本书所谈论的那种事情。

如果const对象包含mutable个数据成员,则可以安全地修改这些成员。 否则,在初始化const对象后对其进行修改是未定义的行为。 这赋予编译器使程序具有任意错误的权限。 这是一个坏主意,你永远不应该这样做。

既然你已经被警告了,那么搬起石头砸自己的脚的方法就是const_cast

原始来源很可能说某些类型的对象可能被系统上的其他硬件或软件修改。 传统上,const volatile用于读取内存映射硬件。 某些设备驱动程序可能需要执行此操作。 现代并行程序可能在共享内存中使用原子变量,读取器线程无法修改这些变量,但将由另一个线程或进程修改。

它只是解释了 const 变量不必放在只读内存中。您无法更改它(因为编译器将显示错误),但可能的事情可以更改。

你的问题

以及如何实现。

是错误的,因为可能改变该值的东西不在您的控制之下。所以你不能"实现"它。

因此,如果不将const值放置在RO存储器中,则可能会更改该值,并且有一些东西(进程或硬件)可以更改此变量占用的存储器位置。

因为你是一个非常初学者(在这个阶段你不会编写多线程程序或设备驱动程序),你可能会完全忽略这句话。

最新更新