代碼:爲什麼你需要添加一個新的字符(str.length())?
string str = "Whats up";
char *c = new char[str.length() + 1];
我仍然可以寫char *c = new char[str.length()];
什麼是上添加長度+1點?
代碼:爲什麼你需要添加一個新的字符(str.length())?
string str = "Whats up";
char *c = new char[str.length() + 1];
我仍然可以寫char *c = new char[str.length()];
什麼是上添加長度+1點?
與std::string
不同,C風格的字符串使用特殊字符來表示其結尾,即空字符'\0'
,多餘的一個字符用於存儲終止的'\0'
。
你的答案可能會引起誤解。 'std :: string'也使用'\ 0'。 'c_str()'方法返回一個指向底層數據的指針,該數據以NULL結尾 – Willem 2014-09-06 09:29:35
代碼中存在缺陷。
應該
c* = new char[str.length()+1];
s.length()+ 1不會做任何事情。
雖然編譯器會自動爲您設置c字符串大小,但指定確切的大小是一種很好的做法,以便您能夠看到所有內容的機制。
C字符串總是需要比std :: string值多一個空格,因爲c字符串是在數組末尾具有終止空值的字符數組。這就是爲什麼你總是在最後給NULL空間。
這根本不回答問題。 – juanchopanza 2014-09-06 07:49:56
你是對的,只是回答了它。 – savageWays 2014-09-06 07:54:48
但「雖然編譯器會自動爲你設置c字符串的大小......」聽起來很不對。 – juanchopanza 2014-09-06 07:56:10
您的代碼:
string str = "Whats up";
char *c = new char[str.length() + 1];
你的問題:
什麼是上添加長度+1點?
真正的問題應該是:在你的C++程序中使用C風格的字符串有什麼意義?你確定你需要他們嗎?
讓我解釋一下到底發生了什麼在你的兩個代碼行:
"Whats up"
是字符串文字,即恆定的一系列字符,一個char const[9]
要精確。第9個字符是空字符,'\0'
,由編譯器自動添加。所以數組實際上是這樣的:
{ 'W', 'h', 'a', 't', 's', ' ', 'u', 'p', '\0' }
事實上,你可能也寫:
char const array[9] = { 'W', 'h', 'a', 't', 's', ' ', 'u', 'p', '\0' };
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);
所以,你可以初始化std::string
與char const *
,你的代碼將構造一個char const[9]
。這是因爲數組自動轉換爲指向其第一個元素的指針。
所以std::string
需要你的數組,把它當作一個指針並複製9個字符。陣列大小信息9
會丟失,但這並不重要,因爲您有終止的'\0'
,因此std::string
知道停止哪裏。
到目前爲止,這麼好。您有一個std::string
對象,其中包含"Whats up"
的副本。你的下一行是這樣的:
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| ...
+-+-+-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
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
,直到找到'\0'
。 str
內部以\0
結尾,所以一切都很好。該功能從到位於此圖片的右側,並將所有內容複製到左側的至。
這最後回答你的問題:左側必須有9個字符的空間。否則,strcpy
將嘗試將最終字符(\0
)寫入不允許觸摸的內存位置。這會導致未定義的行爲並可能導致例如崩潰或隨機崩潰。
客房爲9個字符,strcpy
成功完成:
c
|
|
+------+
|
v 0 1 2 3 4 5 6 7 8
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
... | |W |h |a |t |s | |u |p |\0| | ... |W |h |a |t |s | |u |p |\0| ...
+-+-+-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
0 1 2 3 4 5 6 7 8 ^
|
|
str -------(c_str())-----------+
這個故事的寓意:
使用std::string
。複製std::string
可以使用內部非常類似的機制,但不必記住「+ 1」規則釋放你(除其他討厭的東西):
std::string s1 = "Whats up";
std::string s2 = "...";
s2 = s1;
http://en.wikipedia.org/wiki/Null-terminated_string這是不是從你從那裏獲得代碼的地方解釋的? – juanchopanza 2014-09-06 07:35:28
爲尾部空白騰出空間。你應該在任何情況下使用strdup(),而free()釋放它。 – EJP 2014-09-06 07:52:25