我正在学习Bjarne Stroustrup的“C ++编程语言”,他讲的是类的逻辑和物理常量。
逻辑常量的例子如下:
class A {
int m;
void func() const { m++; } //forbidden
}
可以通过强制转换来绕过它,例如:
class A {
int m;
void func() const { (A*) this)->m++; } //allowed
}
用他的话来说,逻辑常数是
“对用户来说看似不变的对象。”
和物理常数是
“存储在只读存储器中”
作为一个说明,他说
物理常量可以通过只在没有构造函数的类中将对象放在只读内存中来强制执行
我不太明白这句话。有人可以解释如何强制执行物理常量以及如果类有构造函数它不起作用的原因吗?
答案 0 :(得分:13)
答案 1 :(得分:5)
构造函数将写入对象作为构造过程的一部分,但如果对象的内存是只读的,则这不起作用。
物理const
仅适用于可在编译时初始化的对象,因此不需要构造函数。
只能在C ++中明确地创建只读内存,但是许多编译器都有扩展允许你这样做,而大多数现代编译器会将代码和一些数据放在只读内存中(如果CPU架构允许这样做)
在MSVC中,您可以将初始化的全局变量强制存储在只读内存中,方法是将其置于标记为已读但未写入的section中
#pragma section("rosec",read)
__declspec(allocate("rosec")) int j = 0; // this will be in a readonly data segment.
答案 2 :(得分:3)
您需要操作系统的帮助。
在Linux上,您可以调用mprotect将页面呈现为只读。在Windows上,有一个相应的API。
由你来决定一个担心页面边界和对象边界的分配器。
如果你的对象有一个构造函数,它就不能被链接器放入只读部分,因为只读它会阻止构造函数的构建。
如果您有一个POD类,并且您将文件范围内的对象声明为const,则它可能最终位于只读区域。
答案 3 :(得分:2)
对于某些类型的对象,编译器将在编译时构建对象并将其放在只读存储器中。由于这是在编译时完成的,所以只有在没有运行时才能完成时才会发生这种情况,因此你不能拥有构造函数。
struct A
{
int x;
float y;
};
A const a = {5,6.5}; // This object can be built at compile time and placed in read only memory.
答案 4 :(得分:0)
要真正强制执行物理常量,您始终可以对写保护的USB驱动器和/或CD-R进行内存映射。这将允许您创建指向物理 const实例的指针。矫枉过正,但我想我会提到它。
我的理解和经验是,只有代码段(可执行机器代码)中的数据在现代体系结构上是只读的(除非禁用此功能,否则为自修改代码/ JVM类型的东西)。你的编译器会倾向于作弊,在代码段中的字面替换之间徘徊,并依赖和读/写RAM进行指针操作(总是用类型转换覆盖)。
所以缺点是,到目前为止,一个建议提到通过操作系统手动标记内存页面。这可能是您工业强度物理常数的唯一可行选择。那个或我的硬件建议。您的编译器不会为您执行此操作。