【发布时间】:2012-07-14 19:10:43
【问题描述】:
编译器如何控制内存中变量的保护?内存中是否有与私有变量相关的标记位?它是如何工作的?
【问题讨论】:
-
编译器=编译时,内存=运行时,差别很大
标签: c++ memory-management private-members data-protection
编译器如何控制内存中变量的保护?内存中是否有与私有变量相关的标记位?它是如何工作的?
【问题讨论】:
标签: c++ memory-management private-members data-protection
如果您的意思是 private 实例成员,那么在运行时没有任何保护。所有保护都发生在编译时,如果你知道它们在内存中的布局,你总是可以得到一个类的私有成员。这需要了解平台和编译器,在某些情况下甚至可能取决于编译器设置,例如优化级别。
例如,在我的带有 GCC 4.6 的 Linux/x86-64 上,下面的程序完全符合您的预期。它绝不是可移植的,并且可能会在异国情调的编译器上打印出意想不到的东西,但即使是那些编译器也会有自己特定的方式来获取私有成员。
#include <iostream>
class FourChars {
private:
char a, b, c, d;
public:
FourChars(char a_, char b_, char c_, char d_)
: a(a_), b(b_), c(c_), d(d_)
{
}
};
int main()
{
FourChars fc('h', 'a', 'c', 'k');
char const *p = static_cast<char const *>(static_cast<const void *>(&fc));
std::cout << p[0] << p[1] << p[2] << p[3] << std::endl;
}
(复杂的转换是因为void* 是唯一可以转换任何指针的类型。然后void* 可以转换为char* 而无需调用strict aliasing rule。这可能是单reinterpret_cast 也是——实际上,我从不玩这种肮脏的把戏,所以我不太熟悉如何以最快的方式做到这一点:)
【讨论】:
FourChars 必须至少有四个大小,打印它的前四个字节的结果具有依赖于实现,但不是未定义的行为。
reinterpret_cast<>?
编译器的工作是查看某些成员是私有的并禁止您使用它们。编译后它们与其他成员没有任何太大的不同。
有一个重要方面,因为数据成员不需要按照它们在类定义中出现的顺序排列在内存中,但它们是变量所必需的具有相同的访问级别。
【讨论】:
(&a)[1] 不一定是 b,即使它被授予&b > &a)。但是一旦给出了编译器并定义了编译选项,行为就不再依赖于执行。如果它有效,它将永远有效,如果它不...永远不会。事实上,它是不可移植的代码。