2012-03-24 71 views
1

我有一個簡單的問題。我有一個很長的std :: string,我想把它傳遞給一個函數。 我想知道這個字符串將被複制到堆棧然後將傳遞一個副本或類似指針的東西將被傳遞並且不需要額外的空間?編譯器是否將std :: string傳遞給堆棧,並將其傳遞給C++中的函數?

(C++)

  • 我還有一個小問題:有多少內存的字符串的元素採取就像char
+0

你在談論一個'std :: string'嗎? – 2012-03-24 12:07:54

+0

你是什麼意思的字符串?引用文字?的std :: string? – selalerer 2012-03-24 12:08:36

+0

我的意思是std :: string。 – 2012-03-24 12:10:24

回答

4

是的,它會被深拷貝,所以建議使用const引用。

void fun(const std::string & arg) 

通常的std :: string具有2個字段,一個指針指向動態分配的內存和長度,所以它是在64位計算機16 +實際長度。

+3

我期望至少** 3個字段**:指針,當前長度和最大長度。 – Sjoerd 2012-03-24 12:43:04

+1

沒有典型的字符串。 MSVC很胖(但不會爲小字符串分配動態內存),而gcc只是一個指向計數緩衝區的指針(因此即使是一個'char'也會分配動態內存)。 – 2012-03-24 19:40:47

0

擾流警報:我的回答不會是相關的,只是一種優化技術。

如果您不想複製字符串,請編寫您的自定義字符串類,它具有兩個指針或一個大小的指針。在過去,它減少了我很多重複。這將只能以只讀方式工作,並執行copy_on_write,即只有遇到寫入時纔會複製。

+0

對於'std :: string',COW也是可行的,但在實踐中通常比複製+小字符串優化要慢。 – Philipp 2012-03-24 14:06:32

0

當在C++中通過值傳遞參數時,它在概念上被複制。不管這個副本是否真的發生,都是另一個問題,並且取決於參數是如何傳遞的,並且在某種程度上取決於編譯器:顯式允許編譯器刪除某些副本,特別是臨時對象的副本。例如,當你從一個函數返回一個對象,並且我們清楚該對象將被返回時,該副本很可能會被忽略。同樣,將函數的結果直接傳遞給另一個函數時,很可能不會被複制。

除此之外,C++ 2011通過支持移動構造函數增加了另一個可能性。這些涵蓋了一些擴展類似的基礎,但也允許您有更好的控制:您可以明確指出,移動對象而不是被複制是可以接受的。儘管如此,在任何情況下都不會通過引用傳遞對象。

對於每個元素所使用的字節,std::string只使用sizeof(cT)字節(其中cTstd::basic_string的字符模板參數)。但是,在許多情況下,字符串會重新分配空間,並且當字符添加到字符串時肯定會重新分配空間。您可以通過比較size()capacity()並通過reserve()進行一定程度的控制來確定過度配置,儘管此功能不需要擺脫任何過度配置,但capacity()必須至少與最後一個reserve() d一樣多。如果字符串很小(例如最多15個字符),現代實現將不會進行任何分配。這被稱爲字符串優化

關於字符串的實際表示形式:除非它很小,否則將使用一個字作爲存儲地址,每個字用於大小和容量,以及具有有狀態分配器的字符串的大小分配器(通常是另一個詞)。考慮到對齊要求,這意味着在大多數情況下,除了元素之外,字符串還需要四個單詞。通常情況下,小字符串優化使用這些字來存儲字符,如果字符串放在那裏,當然,除非需要存儲有狀態的分配器。