在C ++程序中,存储的是常量数据,尤其是字符串常量?
我在问,因为在下面的问题中:
Why can creating a static const std::string cause an exception?
达蒙的回答,最后有以下几点:
与字符串相反,string_view不会分配非常量 内存,将常量数据复制到其中,然后假装它是常量。 相反,它将直接管理指向常量数据的指针,并且 就是这样。
那样,你的常数在那里真正(不仅仅是正式)不变 没有分配,没有异常的可能性,也没有双重内存 用法。在大多数情况下,它仍然看起来和闻起来像一个字符串。 唯一值得注意的差异是string_view没有 保证nul-termination(但它指向的字符常量) 是的,所以这是无关紧要的),以及它真的不变, 不可修改......这正是你想要的。
甚至连常量都需要存储在内存中的哪些地方?如果它们存储在内存中(因为内存是有限的),是不是可能因为没有更多内存而抛出异常?
答案 0 :(得分:2)
问题是std::string
是一个对象,而不仅仅是普通数据。
这意味着当您声明
时static const std::string foobar = "foobar";
二进制文件中保留的静态数据是文字"foobar"
(用作const char*
)和存储std::string
对象所需的空间,即< strong> NOT 存储其内容所需的空间。
想象一下std::string
就像是,让我们说
class string {
private:
size_t length;
char* data;
public:
string(const char* data) : length(strlen(data), data(new char[length+1]) {
strcpy(this->data, data);
}
~string() { delete data; }
};
这是一段微不足道的不安全代码,但它只是为了给你提供这个想法。当你拥有static std::string
时,唯一需要的空间是sizeof(char*)+sizeof(size_t)
字节,因为数据本身是在堆上动态分配的。
这就是为什么使用static const std::string
浪费两倍的空间:对于文字本身,传递给字符串的构造函数,以及std::string
。
现在这个对象不是&#34;预构建的&#34;在编译时。它是在运行时和标准doesn't guarantee构造的,当它恰好发生时(事实上如果它在调用main
之前发生,你将无法捕获构造函数可能抛出的任何异常)。
引用的string_view
是const char*
的包装器,它不会浪费内存,因为它只存储指向内容的指针,而普通{{1}不是这种情况。设计为可变的。
答案 1 :(得分:1)
静态常量存储在&#39;数据中。可执行文件的一部分。它们存储的确切位置可能因系统而异,但在Linux的情况下,它们作为可执行文件的一部分加载并显示在文本段的正上方。在进程内存映射中。
在程序开始执行之前,操作系统将它们加载到进程内存映射中;因此,如果没有足够的内存,程序甚至无法加载,更不用说抛出异常了!
如果您对流程的内存布局感兴趣,我发现this blog post最有帮助。