其中是存储在内存中的字符串常量
Where are string constants stored in memory?
在C++程序中,常量数据存储在哪里,尤其是字符串常量?
我之所以这么问,是因为在以下问题中:
为什么创建静态conststd::字符串会导致异常?
达蒙的答案在最后有以下内容:
与字符串相反,string_view不会分配非常量内存,将常量数据复制到其中,然后假装它是常量。相反,它将直接管理指向常量数据的指针,并且仅此而已。
这样,你的常数是真正的(不仅仅是形式上的(常数没有分配,没有异常的可能性,也没有双重内存用法在大多数情况下,它看起来和闻起来仍然像一根绳子。唯一显著的区别是string_view没有保证nul终止(但它指向的字符常量是的,所以这是无关紧要的(,而且它实际上是恒定的,不可修改。。。这正是你想要的。
难道连常数都不需要存储在内存中的某个地方吗?如果它们存储在内存中(因为内存是有限的(,难道不可能因为没有更多的内存而引发异常吗?
问题是std::string
是一个对象,而不仅仅是普通数据。
这意味着当你申报时
static const std::string foobar = "foobar";
二进制文件中保留的静态数据是用于文字"foobar"
(用作const char*
(和存储std::string
对象所需的空间的静态数据,该空间是存储其内容所需的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
。
现在,这个对象在编译时不是"预构造的"。它是在运行时构建的,标准并不能保证它何时准确发生(事实上,如果它发生在调用main
之前,则无法捕获构造函数可能引发的任何异常(。
引用的string_view
是const char*
的包装器,它不会浪费内存,因为它只存储指向内容的指针,而设计为可变的普通std::string
则不是这样。
静态常量存储在可执行文件的"data"段中。它们的确切存储位置可能因系统而异,但在Linux的情况下,它们作为可执行文件的一部分加载,并出现在进程内存映射中的"文本段"的正上方。
在程序开始执行之前,操作系统会将它们加载到进程内存映射中;因此,如果内存不足,程序甚至无法加载,更不用说抛出异常了!
如果你对进程的内存布局感兴趣,我发现这篇博客文章非常有用。
- 将错误作为从字符串常量到"char*"的已弃用转换 [-Wwrite-strings]
- 3 与错误最接近的总和:字符串常量之前的预期非限定 id
- 为什么字符串(常量字符* s,size_t pos,size_t len = npos)有效?
- 指向字符串常量的指针
- 警告:ISO C++禁止将字符串常量转换为'char*' [-Wwrite-strings]
- 为什么在波纹管程序中发生了从字符串常量到'char*'的警告已弃用的转换
- 一种创建将字符串常量返回给枚举的类的廉价方法,反之亦然
- 如何从字符串常量创建字符数组
- 将字符串常量转换为char
- C++ 字符串常量和静态初始化顺序惨败
- 使用 std::string 返回开关大小写块中的字符串常量
- 消除从字符串常量到'char*'的已弃用转换的最佳方法"
- 警告:ISO C++禁止将静态“constexpr char*”数据成员的字符串常量转换为“char*”
- 字符常量或字符串常量
- Swig:如何类型映射c ++字符串常量和python字符串?
- 字符串常量之前的预期构造函数、析构函数或类型转换
- 为什么从字符串常量到"char*"的转换在 C 中有效,但在C++中无效
- 警告:已弃用从字符串常量到 'char* 的转换
- 无法获得通过C++警告:(和崩溃后)已弃用从字符串常量到"char*"的转换 [-Wwrite-strings]
- 错误:字符串常量 extern "a" { 之前应为非限定 ID