我有一个简单的程序:
#include <iostream>
#include <string>
#include <string.h>
using namespace std;
string read0() {
int length = 4;
char *cstr = new char[length];
string str(cstr);
delete[] cstr;
return str;
}
string read1() {
int length = 4;
char cstr[length];
memset(cstr, '-', 4);
string str(cstr);
return str;
}
string read2() {
const char* cstr = "abcd";
string str(cstr);
return str;
}
在上面的所有3个函数中,为了构造一个字符串,它们是 call basic_string( const CharT* s, const Allocator& alloc = Allocator()
. 当我使用valgrind / massif检查堆使用情况时,函数read0仅使用4个字节(来自 new
),但read1和read2都使用29个字节 .
这是地块的一些细节输出:
对于read0:
16.67%(4B)(堆分配函数)malloc / new / new [], - all-fns等 - > 16.67%(4B)0x400A0B:read0()(main.cpp:10) - > 16.67% (4B)0x400BC8:main(main.cpp:40)
对于read1和read2:
72.50%(29B)(堆分配函数)malloc / new / new [], - all-fns等 - > 72.50%(29B)0x4EE93B7:std :: string :: _ Rep :: _ S_create(unsigned long, unsigned long,std :: allocator const&)(在/ usr / lib / x86_64-linux-gnu / libstdc .so.6.0.17中) - > 72.50%(29B)0x4EEAD93:char * std :: string :: _ S_construct(char const *,char const *,std :: allocator const&,std :: forward_iterator_tag)(在/ usr / lib / x86_64-linux-gnu / libstdc .so.6.0.17中) - > 72.50%(29B)0x4EEAE71:std: :basic_string,std :: allocator> :: basic_string(char const *,std :: allocator const&)(在/ usr / lib / x86_64-linux-gnu / libstdc .so.6.0.17中) - > 72.50%(29B) 0x400B81:read2()(main.cpp:34) - > 72.50%(29B)0x400BC8:main(main.cpp:40)
是什么导致这种差异?
2 回答
如果我错了,请有人纠正我,但我想我知道为什么会这样 .
在
read0
中,您可以:您根本没有初始化
cstr
,因此可能未定义 . 字符串构造函数采用 null-terminated c-string并将其复制until the null terminator . 我认为它在第一个元素处找到它,所以它只复制指向这样一个字符串的指针,这可能占用4个字节 .我认为你的
read1
是相似的 . 它最终在字符串本身的某个点找到一个空终止符,因为它不是以空值终止的,最终是29个字节 .我不知道为什么
read2
在做同样的事情,说实话 . 可能我上面的read1
的原因是错的,29个字节(减去c字符串中的4个字符/字节)是架构和编译器实现STL时字符串的最小运行成本 .In any case ,为了缩小各种可能性,我建议你在
read0
和read1
中空终止字符串,然后通过分配一个额外的元素并将最后一个元素设置为'\0'
或者使用另外一个额外的字符串构造函数再次尝试实验参数,表示要复制的字符数:在read0中,您正在从cstr初始化str,它是空的(零长度) . 在read1和read2中,您正在从非空字符串初始化str . 在后一种情况下(29字节)实际分配的堆大于严格必要的堆,以使堆管理更快更简单 - 例如,以32字节(或其他一些舍入数字)的块分配堆并不罕见 .
此外,你的read1被窃听:如果你想让cstr包含“----”,那么你需要cstr [5],而不是cstr [4] . 您的数组需要空间用于字符串终止零 . 然后你应该使用strcpy(cstr,“----”)而不是memset(cstr,' - ',4),否则cstr将没有(所需的)零终止符 .