如何创建外部不可修改的变量

How to create externally unmodifiable variable?

本文关键字:修改 变量 外部 何创建 创建      更新时间:2023-10-16

我正在开发简单的模拟库,遇到了问题,其中我有模拟Time变量,在任何情况下都不应该被API用户(程序员)修改(只提供有关模拟时间的信息),但应该可以通过模拟库修改,所以它不能是恒定的。

这就是我想出的,但对我来说似乎有点棘手

double simTime;                // Internal time, modified by library
const double& Time = simTime;  // Time info provided for programmer in API

有没有办法在没有const double&的情况下解决这个问题?

您可以

更改 API 以提供返回 simTime 值的函数double getTime();,而不是const double &

我发现const double&解决方案相当直接和优雅,我没有看到任何负面的副作用。

唯一的问题是,您的库应该将simTime声明为 static 或匿名命名空间中,以便无法从外部寻址。否则,任何其他翻译单元中的任何extern double simTime都会暴露simTime

所以写...

// library.cpp:
static double simTime;
const double &simTimePublic = simTime;
// library.h:
extern const double &simTimePublic;
// userCode.cpp:
#include "library.h"
...
double simTimeCopy = simTimePublic;
// simTimePublic = 1.0; // illegal

您甚至可以(在公共标头中)定义一些内联函数,返回一个外部变量,其名称足够长,不容易被猜到,例如

static inline double getTime(void) {
  extern double somelongname_simTime; // don't use that name directly
  return somelongname_simTime;
}

事实上,名称somelongname_simTime是公开的,但需要直接使用用户的恶意(因为它不是在公共头文件的文件范围内声明的)。

(你甚至可以使用namespace技巧)

请注意,编译器无法阻止未定义的行为,例如指针意外获取static变量的地址。

在Linux上,你甚至可以玩一些可见性技巧。


特别是对于 GCC,您可以尝试将两个名称用于相同的全局内存位置(使用汇编器标签),例如在您的公共标头中

extern volatile const double simTime_public asm ("myrealsimTime");

在某些实现文件中,您将拥有

double simTime_private asm("myrealsimTime");

当然,在玩这种技巧时,您是在滥用编译器和链接器。

(显然你可以混合使用这两种方法)。