当分配一个字符串值并稍后通过分配另一个值进行更改时C++如何管理内存?

How is C++ memory managed when a string value is assigned and later changed by assigning another value?

本文关键字:分配 C++ 内存 管理 何管理 字符串 一个 另一个      更新时间:2023-10-16

我真的需要了解在以下情况下如何C++管理内存:

案例-1:

string s1 = "ABCD";
s1= "EFGH";

在字符串值"ABCD"的内存中会发生什么?它会自动解除分配吗?还是这里的内存泄漏?

案例2:

char* val = "ABCD";
val = "EFGH";

与案例 1类似,案例 2 与案例 1 有何不同?

案例3:

string s1 = "ABCD";
string s2 = s1;

是否为值为"ABCD"的 s2 分配了单独的内存?还是 s1 和 s2 指向此处的相同内存位置? 在这种情况下,如何管理内存?

请分享一个链接以深入研究这些?任何建议肯定会对我有所帮助。

  1. 现代std::string实现大致遵循这些规则(这里也解释得很好(:

    • 短字符串(<=26 个字符?(使用称为 SSO 的优化在堆栈上分配。
    • 字符串
    • 长度超过堆上分配的字符串。std::string 实现在内部管理此处的分配和解除分配。
  2. const char* x = "ABCD"在静态存储中的堆栈上分配,指向它的指针存储在堆栈上。这可以从此处的CE链接中看到,其中rsp:rsp-8指向.LC0

鉴于上述观察结果:

  • 情况 1:它在堆栈上分配 x,然后将新值"EFGH"复制到 s1,而不分配更多的堆栈空间。CE 链接
  • 情况 2:它使val指向存储"ABCD"的静态存储,然后指向"EFGH"所在的位置。CE 链接
  • 情况
  • 3:这将(未启用优化(在堆栈(CE 链路(上分配 2 个 std::string,遵循情况 1。

如注释中所述,替代std::string实现是可能的,例如 (1( 那些不实现 SSO 的实现 (2( 实现写入时复制。

案例 1

string s1 = "ABCD";

string处理内存分配以为您存储"ABCD"。当string析构函数超出范围时,将自动调用s1,这将释放string分配的内存。

s1 = "EFGH";

string复制赋值运算符将使用"EFGH"覆盖内存存储"ABCD"

案例2

char* val = "ABCD";
val = "EFGH";

Fred Larson 在上面的评论中回答了这个问题,你只是重新分配了一个指向静态字符串的指针。堆栈将仅为指针(而不是数据(分配内存,当指针超出范围时val将自动释放。

案例3

string s1 = "ABCD";
string s2 = s1;

s2将分配内存并复制s1。复制赋值运算符的写入时复制实现只会在s2发生突变时分配和复制内存。但是,从 C++11 开始,似乎不再允许 COW 实现std::string(C++11 中 COW std::string 实现的合法性(。

案例4

下面是一个方案示例,在该方案中,您确实需要担心释放分配的内存。

如果需要一个string来超过创建它的范围,则可以使用它。(在实践中,通常应避免使用此方法。请参阅下面的案例 5

string* s1 = new string("ABCD");
delete s1;

在此示例中,string仍在内部管理内存以存储"ABCD",但string指针是堆分配的,并且当s1超出范围时不会调用string析构函数。在这种情况下,您负责使用delete来确保在不再需要内存时清理内存s1

案例5

shared_ptr<string> s1 = make_shared<string>("EFGH");

shared_ptr通常是要走的路,而不是newdelete。共享指针可防止由于编程错误而导致的大量内存泄漏。shared_ptr为您处理delete,并使用引用计数使string保持活动状态,直到最后一个引用被销毁。