std::string 在内存中分配的位置在哪里?

Posted

技术标签:

【中文标题】std::string 在内存中分配的位置在哪里?【英文标题】:Where is a std::string allocated in memory? 【发布时间】:2017-02-05 08:00:49 【问题描述】:

这是一个函数:

void foo() 
   string str = "StackOverflo";
   str.push_back('w');

当我们在函数内部声明字符串时,它是存储在堆栈还是堆中?为什么?

string foo() 
   string str = "StackOverflo";
   str.push_back('w');
   return str;

我们可以返回字符串引用并继续在程序的其他地方使用吗?

【问题讨论】:

返回对局部变量的引用/指针是一种未定义的行为。您的代码返回字符串本身,这完全没问题 【参考方案1】:

当我们在函数内部声明String时,是存放在Stack还是Heap?

字符串对象本身存储在堆栈中,但它指向堆上的内存。

为什么?

语言被定义为将字符串对象存储在堆栈中。 string 构造对象的实现使用堆上的内存。

【讨论】:

当我们从函数返回字符串时会发生什么?它会发送字符串的副本并且字符串从内存中消失吗?或者它会返回一个指向该内存的指针,然后它就会消失? @AndreiMargeloiu 它将返回 std::string 的副本,只要将其存储在某处就可以使用。你不必担心它的内部数据 std::string 完美地处理它自己的数据字符指针 @AndreiMargeloiu 从概念上讲,调用函数可以使用返回值构造一个新对象,该对象将使用复制构造函数,或者分配给现有对象,该对象将使用复制赋值运算符.这些函数中发生的事情再次由string 类定义。 @AndreiMargeloiu 还要查找“复制省略”。 @AndreiMargeloiu,是的。如果你会使用 C++11,你会发现this article on rvalue references and move semantics 很有趣。【参考方案2】:

对象str(它是类std::string的实例)在堆栈中分配。然而,字符串数据本身可能被分配在堆中。这意味着该对象有一个指向包含实际字符串的缓冲区的内部指针。但是,同样,如果字符串很小(如本例中),通常字符串类将具有我们所说的“小字符串优化”。这意味着std::string 对象本身的大小足以包含字符串的数据,如果它足够小(通常大约 23 字节 + 1 字节用于空终止符)......那么如果内容大于这个,字符串数据将在堆中分配。

通常你可以正常返回你的字符串。 C++ 可以为您处理这个问题。移动语义可以在这里处理任何必要的事情,以返回指向与原始字符串相同的字符串数据的字符串对象,避免进行不必要的复制。

【讨论】:

除了move之外还有返回值优化:en.wikipedia.org/wiki/Copy_elision#Return_value_optimization这样连move都不需要,字符串可以构造成返回值。 那么为什么字符串的内容会存储在堆上呢?为什么不在堆栈上? (对于大字符串) 因为栈比堆小很多,会导致“栈溢出” @WagnerPatriota 感谢您终于回答了悬而未决的问题。【参考方案3】:

"StackOverflo",字符串文字,很可能存储在二进制的只读数据空间中,并在程序启动时映射到内存中。你可以阅读更多关于这个here的信息。

str,类实例`,在堆栈上分配。但是它的构造函数分配的用于制作字符串文字的副本的内存是在堆上分配的。

foo 函数返回str副本,所以你写的代码没问题。

【讨论】:

但是它的构造函数为复制字符串文字而分配的内存是在堆上分配的。除非字符串足够小。然后小字符串优化可能会开始。【参考方案4】:

C++ 中的所有局部变量都存储在 Stack 中。甚至本地指针也存储在堆栈中。但是指针中分配的内存存储在堆上。

因此,您的str 存储在堆栈中,而其值存储在堆中。 因为std::string 使用char 指针来分配你的"***"

【讨论】:

实际上,它可能比这更复杂。许多 C++ 实现都有所谓的小字符串优化。对于一些小字符串,它们的内容在string 实例内(不在堆上)。细节是特定于实现的。 有些系统也没有栈【参考方案5】:

在 Windows 平台上,在 C++ 中,使用 std::string,小于大约 14 个字符左右的字符串(称为小字符串)存储在堆栈中,几乎没有开销,而上面的字符串大小存储在堆中,有开销.通常取决于平台和编译器,可以使用优化选项进行调整。

std::string myStr "Hello World"; // 存放在程序栈中 std::string myStr "*** 挽救了程序员的生命" ; //指针存储在程序堆栈中,而字符串存储在堆中

下面的链接有很好的解释。 https://blogs.msmvps.com/gdicanio/2016/11/17/the-small-string-optimization/

【讨论】:

【参考方案6】:

当我们在函数中声明字符串时,它是否存储在 堆栈还是堆?为什么?

在堆上分配的最大也是可能唯一的原因是允许字符串对象的大小增长,例如通过调用push_back()append()。存储在堆栈中的对象无法更改其大小 - 这是由 C/C++ 语言定义的。

【讨论】:

以上是关于std::string 在内存中分配的位置在哪里?的主要内容,如果未能解决你的问题,请参考以下文章

在共享内存中共享std :: string

如何在 C# 中释放在 C++ 中分配的内存

在 C++ 中清除堆栈中分配的内存

查找程序中分配的内存? [复制]

JAVA里String数组在内存分配中分配的空间每个占几个字节?

如何释放在我的 RPC 服务器中分配的内存?