簡體   English   中英

立即定義帶有值的字符串時建議的速度提升,而不是延遲

[英]Suggested speed improvement when defining string with value immediately, instead of delaying

我目前正在閱讀Bjarne Stroustrup撰寫的“The C ++ Programming Language:Special Edition”和第133頁,其中說明如下:

對於用戶定義的類型,將變量的定義推遲到合適的初始化程序可用之后,也可以獲得更好的性能。 例如:

 string s; /* .... */ s = "The best is the enemy of the good."; 

很容易慢得多

 string s = "Voltaire"; 

我知道狀態很容易 ,這意味着它不一定是這樣,但是我們只是說它確實發生了。

為什么這會帶來潛在的性能提升?

它只是用戶定義的類型(甚至是STL類型),還是intfloat等的情況呢?

我會說這主要是關於具有非平凡默認構造函數的類型,至少就性能而言。

兩種方法的區別在於:

  • 在第一個版本中,首先構造一個空字符串(使用默認構造函數); 然后賦值運算符用於有效地丟棄默認構造函數完成的工作,並將新值賦給字符串。
  • 在第二個版本中,在構造點立即設置所需的值。

當然,事先告訴我們這會產生多大的性能差異真的很難。

  1. 執行默認構造函數需要時間。 覆蓋它在隨后調用的賦值運算符中初始化字符串的內容也需要時間。

  2. 當函數(由於return語句或異常)在默認構造函數和賦值運算符的調用之間留下時,執行可能永遠不會到達賦值。 在這種情況下,對象被不必要地默認初始化

  3. 實現可能會浪費性能以確保在拋出異常時調用對象析構函數 如果在后續范圍內初始化對象,則從未達到該范圍,也不需要。

因為:

string s;  /* .... */ s = "The best is the enemy of the good.";    

涉及兩個操作:構造和分配

而:

string s = "Voltaire";   

僅涉及施工。

這相當於在構造函數體中的Assignment上選擇Member Initializer列表

這是個好問題。 你是對的,這只發生在復雜的類型中。 即類和結構,std :: string就是這樣一個對象。 這里涉及的真正問題與構造函數有關。

創建對象時,即

std::string s;

它的構造函數被調用,它可能會分配一些內存,做一些其他的變量初始化,讓它自己准備好使用。 實際上,代碼中此時可以執行大量代碼。

稍后你會做:

s = "hello world!";

這導致類必須拋棄它所做的大部分工作,並准備用新字符串替換它的內容。

如果在定義變量時設置值,則實際上減少為單個操作,即:

std::string s = "Hello world";

事實上,如果您在調試器中查看代碼,請執行一次不同的構造函數,而不是構造對象,然后單獨設置一個值。 實際上,之前的代碼與以下代碼相同:

std::string s("Hello world");

我希望這有助於澄清一些事情。

考慮兩種情況都會發生什么。 在第一種情況下:

  • 默認構造函數調用“s”
  • 賦值運算符調用“s”

在第二種情況下,首先考慮使用copy elision,這相當於string s("Voltaire") ,因此:

  • c-string構造函數調用

邏輯上,第一種方法需要抽象機器做更多的工作。 這實際上是否轉換為更實際的代碼取決於實際類型以及優化器可以執行的操作。 雖然請注意,對於除了普通用戶類型以外的所有用戶類型,優化器可能必須假設默認構造函數具有副作用,因此不能簡單地將其刪除。

此額外成本應僅適用於用戶類型,因為成本在默認構造函數中。 對於像int這樣的任何原始類型,或者實際上任何具有普通構造函數/副本的原始類型,默認構造函數都沒有成本 - 數據根本不會被初始化(在函數范圍內)。

為什么這會帶來潛在的性能提升?

第一種情況涉及默認初始化,然后是分配; 第二個涉及從價值初始化。 默認初始化可能會做一些以后必須通過賦值重做(甚至撤消)的工作,因此第一種情況可能涉及比第二種情況更多的工作。

它只是用戶定義的類型(甚至是STL類型),還是int,float等的情況呢?

只有用戶定義的類型才是這樣; 然后它取決於構造函數和賦值運算符實際執行的操作。 對於標量類型,默認初始化不執行任何操作,並且賦值與從值初始化完成相同的操作,因此兩個備選方案都是等效的。

該類有三種方法來初始化字符串:

string  s;         // Default constructor
string  s = "..."; // Default constructor followed by operator assignment
string  s("...");  // Constructor with parameters passed in

字符串類需要分配內存。 一旦知道需要多少內存,最好分配它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM