簡體   English   中英

string += s1 和 string = string + s1 的區別

[英]Difference between string += s1 and string = string + s1

我的一個程序在使用時超過了時間限制fans = fans + s[i] ,而當我使用fans += s[i]它被接受了......為什么會發生這種情況? 為了解釋更多,fans 是一個字符串,s 也是一個字符串,所以在迭代字符串 si 時只需要 s 的一些字符,所以我正在創建一個新的字符串 fans。現在有兩種方法可以向我的新字符串添加字符粉絲。 問題在下面提到

fans = fans + s[i]; // gives Time limit exceeded 
fans += s[i];       // runs successfully

對於內置類型a += ba = a + b完全相同(除了a只計算一次),但對於類,這些運算符被重載並調用不同的函數。
在您的示例中, fans = fans + s[i]創建一個臨時字符串,並將其分配(移動)給fans ,但fans += s[i]不會創建該臨時字符串,因此它可能會更快。

std::string有成員operator +operator += 前者通常通過中間臨時的方式與后者一起實現。 有效地看起來像這樣(如果您想確切地知道您的實現源,請檢查您的實現源):

/// note reference return type
std::string& operator +=(char c) 
{
    this->append(c);
    return *this;
}

// note value return type
std::string operator +(char c) const
{
    std::string tmp = *this;
    tmp += c; // or just tmp.append(c) directly
    return tmp;
}

tmp的設置很昂貴。 整體功能可以(並且通常)通過移動分配語義在調用方的最終目的地變得更好,但臨時的費用仍然存在。 做幾次,你不會注意到差異。 這樣做數千次,或數百萬次,等等,這可能意味着一個不同的世界

如果您使用fans=fans+s[i] ,則字符串將在每次循環中復制。 新元素將添加到字符串的副本中,結果將重新分配給變量fans 在此之后,必須刪除舊字符串,因為它不再被引用。 這需要花費大量時間。

如果您使用增強賦值fans+=s[i]字符串將不會在每次循環中都被復制,並且不需要刪除引用變量,因為這里沒有引用變量。 這樣可以節省很多時間。

我希望你現在能理解!!

對於基本類型, a = a + ba += b表示相同的意思。

對於任意的類類型, a = a + ba += b是不相關的; 他們查找不同的運算符,這些運算符可以做任意的事情。 它們實際上無關的是代碼異味,這是設計問題的標志。

a = a + b大致變成operator=( a, operator+( a, b ) ) 實際的查找規則有點復雜(涉及成員運算符和非成員運算符,以及=沒有非成員運算符等事實),但這就是它的核心。

a += b在類似的意義上變成operator+=( a, b )

現在,在+=方面實現+是一種常見的模式; 如果你這樣做,你會得到:

a = a + b

變成

a = ((auto)(a) += b);

其中(auto)是新的 / “創建參數的臨時副本”功能。

從根本上說, a+=b可以重用的內容a直接,而a = a + b不能; 在評估a+b的那一刻,它不知道a很快就會被覆蓋。

一些庫使用一種稱為“表達式模板”的技術來處理這個問題; a+b不是值,而是表達式a+b的編譯時描述,當分配給a時,它實際上用於用數據填充a 使用表達式模板,消除了a+=ba=a+b知道更多的基本問題。

現在,對於std::string具體地, a+b創建了一個臨時字符串對象,則a=(a+b)移動到這a (它可以重復使用臨時字符串對象的緩沖器或緩沖a ,標准為對此事保持沉默)。

a+=b必須重用a緩沖區中的任何多余容量。 所以如果你a.reserve(1<<30) (10 億), a+=b不能分配更多。

暫無
暫無

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

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