是否可以在C++中使变量真正只读

Is it possible to make variable truly read-only in C++?

本文关键字:变量 只读 C++ 是否      更新时间:2023-10-16

通过使用const限定符,变量应该是只读的。例如,标记为constint不能分配给:

const int number = 5; //fine to initialize
number = 3; //error, number is const

乍一看,这使得无法修改number的内容。不幸的是,实际上它是可以做到的。作为示例,可以使用const_cast(*const_cast<int*>(&number) = 3)。这是未定义的行为,但这并不能保证number实际上不会被修改。它可能会导致程序崩溃,但也可以简单地修改值并继续。

是否有可能使实际不可能修改变量?

可能的需要是出于安全考虑。最重要的可能是,某些非常有价值的数据不得更改,或者发送的数据不得修改。

不,这不是编程语言所关心的问题。任何";访问";保护只是表面的,只存在于编译时。

如果您拥有相应的权限,则可以在运行时修改计算机的内存。不过,您的操作系统可能会为您提供保护内存页的设施,例如Windows下的VirtualProtect()。

(请注意,"攻击者"如果有权限,可以使用相同的设施恢复访问)

此外,我认为可能有硬件解决方案。

还可以选择对有问题的数据进行加密。然而,这似乎是一个先有鸡后有蛋的情况,因为加密和解密的私钥也必须存储在内存中的某个地方(使用仅限软件的解决方案)。

虽然这个线程中的大多数答案都是正确的,但它们与const有关,而OP正在寻求一种在源代码中定义和使用常数值的方法。我的水晶球说OP正在寻找符号常量(预处理器#define语句)。

#define NUMBER 3
//... some other code
std::cout<<NUMBER;

通过这种方式,开发人员能够参数化值并轻松维护它们,而一旦程序被编译和启动,几乎没有(简单的)方法来更改它。

请记住,常量变量对调试器可见,而符号常量则不可见,但它们不需要额外的内存。另一个标准是类型检查,这在符号常量和宏的情况下是不存在的。

const不打算将变量设为只读

const x的含义基本上是:

嘿,编译器,请防止我在这个范围内随意编写更改x的代码。

这与非常不同

嘿,编译器,请阻止在此范围内对x进行任何更改。

即使你自己不写任何const_cast的,编译器仍然不会认为const的实体不会改变。具体来说,如果您使用功能

int foo(const int* x);

编译器不能假设CCD_ 15不改变CCD_。

你可以在没有变量的情况下使用你的值

变量各不相同。。。因此,自然地,防止这种情况的一种方法是使用不存储在变量中的值。你可以通过使用。。。

  • 具有单个值的枚举:enum : int { number = 1 }
  • 预处理器:CCD_ 18<-不推荐
  • a函数:inline int get_number() { return 1; }

您可以使用特定于实现/平台的功能

正如@SebastianHoffman所建议的,典型的平台允许将进程的一些虚拟内存空间标记为只读,因此试图更改它会导致进程的访问违规信号并暂停执行。这不是语言本身的解决方案,但它通常是有用的。示例:当您使用字符串文字时,例如:

const char* my_str = "Hello world";
const_cast<char*>(my_str)[0] = 'Y';

您的流程可能会失败,并显示以下消息:

Segmentation fault (core dumped)

如果您在编译时了解程序,则可以将数据放在只读内存中。当然,有人可以绕过这一点,但安全是关于层次而不是绝对的。这就更难了。C++对此没有概念,所以您必须检查生成的二进制文件,看看它是否发生了(这可以作为构建后检查编写)。

如果您在编译时没有该值,那么您的程序依赖于是否能够在运行时更改/设置它,因此您根本无法阻止这种情况的发生。

当然,你可以让它变得更难,尽管像const这样的东西,所以代码是在假设它不会改变的情况下编译的/程序员不小心改变了它会更难。

您还可以在这里找到一个有趣的工具constexpr

没有办法指定哪些代码不符合规范。

在您的示例中,number确实是恒定的。您正确地注意到,在const_cast之后修改它将是未定义的beahvior。事实上,在正确的程序中修改它是不可能的。