如果向量总是提供连续的内存存储,那么编译器如何分配内存以清空std :: strings?
我有一个向量,我用std:string作为私有成员推送了许多类。然后我将对向量的引用作为另一个方法的参数传递。
堆中其他位置的字符串数据是否是从向量的连续数组引用的?
答案 0 :(得分:4)
为std::string
分配内存琐碎。
在内部,它会有某种指针指向一个内存块,其中将存储实际的字符串数据。因此,为std :: string分配内存只是为指针,size_t
或其他东西分配空间,可能还有几个原语。
例如,如果您有std::vector<std::string>
,则向量可以轻松为std::string
分配空间,因为它们只是k
每个字节都有一些常量k
。字符串数据不会参与此分配。
答案 1 :(得分:1)
在这种情况下,内存中真正发生的事情的细节完全取决于您正在使用的特定STL实现。
话虽如此,我的印象是,在大多数实现中,vector和string都是用( very 简化)之类的方式实现的:
template<typename T>
class vector
{
//...
private:
T* _data;
};
class string
{
private:
char _smallStringsBuffer[kSmallSize];
char* _bigStringsBuffer;
};
矢量的数据是根据容量在默认情况下在堆上动态分配的(默认初始化时具有默认值,在向量中添加元素时会增长)。
字符串的数据静态分配给小字符串(依赖于实现的值&#34; small&#34;),然后在字符串变大时动态分配。出于多种原因,情况就是如此,但主要是为了更有效地处理小字符串。
您描述的示例如下:
void MyFunction(const vector<string>& myVector)
{
// ...
}
int main()
{
vector<string> v = ...;
// ...
MyFunction(v);
// ...
return 0;
}
在这种特殊情况下,只有向量v的基本数据将在堆栈中,因为v._data将在堆上分配。如果v的容量为 N ,则堆中的v._data的大小将为sizeof(string)* N,其中字符串的大小是一个常量,它将取决于kSmallSize * sizeof( char)+ sizeof(char *),基于上面字符串的定义。
对于连续数据,只有当向量中收集的所有字符串都具有比kSmallSize更少的字符时,它们的数据才会是&#34;几乎&#34;在记忆中连续。
这是性能关键代码的一个重要考虑因素,但说实话,我不认为大多数人会依赖标准STL的向量和字符串来处理这种情况,因为实现细节可能会改变随着时间的推移,在不同的平台和编译器上。此外,每当你的代码超出&#34; fast&#34;路径,你不会注意到,除了延迟的尖峰将难以控制。