std::string and const char *

3
如果我使用

const char * str = "Hello";

在运行时不需要进行内存分配/释放

如果我使用

const std::string str = "Hello";

在string类中是否会使用new/malloc进行分配?我在汇编中找到了它,但我不擅长阅读。

如果答案是“是的,会有malloc/new”,为什么?为什么只能通过内部const char指针传递并在需要编辑字符串时进行实际内存分配?


这不取决于你的实现吗? - Carl Norum
1
请注意,这两个代码示例并不相等,因为第二个允许修改字符串。请思考它们的含义:char str[] = "Hello"; 或者 const std::string str = "Hello"; 甚至是 static const std::string str = "Hello" - Neil Kirk
@NeilKirk 没错,我已经编辑了答案。 - Martin Perry
3个回答

5
会不会在string类中使用new/malloc进行内存分配呢?这要看情况而定。因为string对象需要提供一些内存来存储数据,所以有些实现采用“小字符串优化”,其中对象包含一个小缓冲区,只有当字符串太大时才从堆中分配。

为什么只能通过内部const char指针传递并且只有在需要编辑字符串时才实际进行内存分配呢?你描述的并不一定是一种优化(因为每次修改字符串时都需要额外的运行时检查),而且在任何情况下都不符合迭代器失效规则。

有一个string_view的提案,允许您使用类似于const string的接口访问现有的字符序列,而无需进行任何内存管理。它尚未成为标准,并且不允许您修改字符串。


string_view 看起来很有趣,因为我大部分时间都有 const 字符串 - 只填充一次并且几乎不修改(由于几乎,const char * 对我来说不是最好的解决方案) - Martin Perry

1
< p > 当实例化 < code > std::string 时,天真的实现需要进行堆分配,然而编译器允许通过替换静态初始化的 < code > std::string 对象为其他实现对象来优化,如果在运行时未修改初始化的字符串。< / p> < p > 您可以使用 < code > const std::string 来实例化不可变字符串,以确保更好的优化。< / p>

定义“最大优化”。在一个函数中,static const std::string 会更加“优化”,因为每次调用函数时可能会减少动态分配。 - Neil Kirk
你是对的。我的方法更偏向于使用栈,而不是整个内存空间。 - diegoperini
您假设字符串数据将在堆栈上。 - Neil Kirk

0

C++标准实际上并没有说你不能只存储一个指向外部字符串的指针(和长度)。然而,这意味着每次你可能修改字符串(例如char& std::string::operator[](size_t index))都必须确保字符串是可写的。由于大量的字符串使用并不仅仅用于存储字符串的常量,而是确实修改字符串[或者使用一个不是常量输入的字符串]。

所以,一些问题是:

std::string s = "Hello";
char &c = s[1]; 
c = 'a';    // Should make string to "Hallo". 

如果发生以下情况:
char buffer[1000];
cin.getline(buffer);   // Reads "Hello"
std::string s = buffer;
cin.getline(buffer);   // Reads "World"

s现在的值是多少?

有很多这样的情况,如果你只是复制原始字符串,会导致更多问题,而几乎没有好处。


因为我的字符串在90%的情况下是只读的(我将它们用作哈希键),所以额外的检查对我来说没问题。至于你的第二个例子...它不是const char *,所以我预计会复制到std::string中,并且缓冲区没有封装在字符串s中。 - Martin Perry
1
当然可以编写自己的类“const_string”或类似的类,确实不允许修改,并使用指针。考虑到这种字符串只允许进行少量操作,编写这样的类应该不需要太长时间。 - Mats Petersson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接