我有一个简单的程序:
#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;
}
Run Code Online (Sandbox Code Playgroud)
在上面的所有3个函数中,用于构造字符串,它们call basic_string( const CharT* s, const Allocator& alloc = Allocator()
.当我使用valgrind/massif检查堆使用情况时,函数read0仅使用4个字节(from 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中) 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)
是什么导致这种差异?
如果我错了,请有人纠正我,但我想我知道为什么会这样.
在read0
,你这样做:
char *cstr = new char[length];
string str(cstr);
Run Code Online (Sandbox Code Playgroud)
你根本没有初始化cstr
,所以它可能是未定义的.字符串构造函数采用以null结尾的 c-string并将其复制到null终止符.我认为它在第一个元素中找到它,所以它只复制指向这样一个字符串的指针,大概占用4个字节.
我觉得你read1
很相似.它最终在字符串本身之后的某个点找到一个空终止符,因为它不是以空值终止的,最终是29个字节.
read2
老实说,我不知道为什么做同样的事情.可能是因为read1
上面的原因我错了,29个字节(减去c字符串中的4个字符/字节)是架构和编译器实现STL时字符串的最小运行成本.
在任何情况下,为了缩小各种可能性,我建议你在null中终止字符串read0
并read1
再次尝试实验,方法是分配一个额外的元素并设置最后一个元素,'\0'
或者使用另一个第二个参数的替代字符串构造函数表示要复制的字符数:
string(non_null_terminated_string, this_many_characters_to_copy)
Run Code Online (Sandbox Code Playgroud)