代码:
string str = "Whats up";
char *c = new char[str.length() + 1];
我仍然可以写char *c = new char[str.length()];
在长度上加+1有什么意义?
您的代码:
string str = "Whats up";
char *c = new char[str.length() + 1];
您的问题:
在长度上加+1有什么意义?
真正的问题应该是:在你的C++程序中使用C风格的字符串有什么意义?您确定需要它们吗?
让我解释一下您的两个代码行中到底发生了什么:
"Whats up"
是一个字符串文字,即一系列常量字符,准确地说是char const[9]
。第 9 个字符是编译器自动添加的空字符 ' '
。所以数组实际上看起来像这样:
{ 'W', 'h', 'a', 't', 's', ' ', 'u', 'p', ' ' }
事实上,你也可以写:
char const array[9] = { 'W', 'h', 'a', 't', 's', ' ', 'u', 'p', ' ' };
std::string s = array;
所以你有一个char const[9]
数组,用于初始化std::string
。这里实际使用了std::string
的哪个构造函数?如果你看一下 http://en.cppreference.com/w/cpp/string/basic_string/basic_string,你会发现这个:
basic_string( const CharT* s,
const Allocator& alloc = Allocator() );
请记住,std::string
实际上是std::basic_string<char>
的typedef,所以在这种情况下,你的CharT
是一个char
,构造函数读作:
string( const char* s,
const Allocator& alloc = Allocator() );
同时忽略alloc
参数。它太复杂了,无法向初学者解释,而且它有一个默认参数,因此您几乎可以一直忽略它。这意味着你最终会得到:
string( const char* s);
这本身就是另一种写作方式:
string(char const *s);
所以你可以用char const *
初始化std::string
,你的代码会char const[9]
传递给构造函数。这是有效的,因为数组会自动转换为指向其第一个元素的指针。
因此,std::string
获取您的数组,将其视为指针并复制 9 个字符。数组大小信息9
会丢失,但这并不重要,因为您有终止' '
,因此std::string
知道在哪里停止。
目前为止,一切都好。您有一个包含 "Whats up"
副本的 std::string
对象。您的下一行是这样的:
char *c = new char[str.length() + 1];
首先,考虑str.length()
.length
函数返回字符串大小,而不是数组大小。因此,尽管您传递了 9 个字符来构造字符串,但 length
返回 8。这是有道理的,因为std::string
旨在让您忘记指针、数组和内存操作。这是文本,这里的文本有 8 个字符。
因此,str.length() + 1
等于 8 + 1 = 9,因此您的代码行等效于:
char *c = new char[9];
您已经创建了一个名为 c
的指针,初始化为指向一个内存位置,该位置有足够的空间容纳 9 个字符,尽管当前存储在那里的内容尚未定义,因此您一定不要尝试从那里读取:
c
|
|
+------+
|
v
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
...| | | | | | | | | | | | ...
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
0 1 2 3 4 5 6 7 8
您创建的std::string
与c
指向的内存之间没有任何关系。他们住在完全不同的地方:
c
|
|
+------+
|
v 0 1 2 3 4 5 6 7 8
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
... | | | | | | | | | | | | ... |W |h |a |t |s | |u |p | | ...
+-+-+-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
0 1 2 3 4 5 6 7 8 ^
|
|
str -------( c_str() )-----------+
但是,如果您使用像 strcpy
这样的 C 函数将std::string
的内容复制到这 9 个字符,那么很明显为什么您需要 9 个字符的空间:
strcpy(c, str.c_str());
strcpy
查看源(str.c_str()
(并复制一个接一个的字符进行c
,直到找到' '
。 str
内部以