[英]Append int to std::string
我嘗試了兩種不同的方法將int
附加到std::string
,令我驚訝的是,我得到了不同的結果:
#include <string>
int main()
{
std::string s;
s += 2; // compiles correctly
s = s + 2; // compiler error
return 0;
}
為什么它編譯和正常工作時,我使用+=
運算符,但不能當我使用+
運算符?
我不認為問題類似於如何連接 std::string 和 int?
在那個問題中,沒有答案使用+=
運算符。而std::string
+=
和+
運算符之間的區別是解決我疑問的關鍵。
坦率地說,這個問題是解釋為什么 c++ 如此難以掌握的一個很好的例子。
TL;DR operator+=
是class string
的類成員函數,而operator+
是模板函數。
標准類template<typename CharT> basic_string<CharT>
重載了函數basic_string& operator+=(CharT)
,而字符串就是basic_string<char>
。
由於適合較低類型的值可以自動轉換為該類型,因此在表達式s += 2
, 2不會被視為int
,而是被視為char
。 它與s += '\\x02'
具有完全相同的效果。 附加了 ASCII 代碼 2 (STX) 的字符,而不是字符“2”(ASCII 值為 50 或 0x32)。
但是,string 沒有像string operator+(int)
這樣的重載成員函數, s + 2
不是有效的表達式,因此在編譯過程中會引發錯誤。 (更多見下文)
您可以通過以下方式在字符串中使用 operator+ 函數:
s = s + char(2); // or (char)2
s = s + std::string(2);
s = s + std::to_string(2); // C++11 and above only
對於擔心為什么 2 不會使用operator+
自動轉換為char
,
template <typename CharT>
basic_string<CharT>
operator+(const basic_string<CharT>& lhs, CharT rhs);
以上是s + 2
加號運算符的原型[注] ,由於是模板函數,所以需要同時實現operator+<char>
和operator+<int>
,這是沖突的。 有關詳細信息,請參閱為什么不將自動向下轉換應用於模板函數?
同時, operator+=
的原型為:
template <typename CharT>
class basic_string{
basic_string&
operator+=(CharT _c);
};
你看,這里沒有模板(它是一個類成員函數),所以編譯器從類實現中推斷出 CharT 類型是char
,並且int(2)
自動轉換為char(2)
。
注意:從 C++ 標准包含源復制時,會刪除不必要的代碼。 這包括模板類“basic_string”的 typename 2 和 3(特征和分配器),以及不必要的下划線,以提高可讀性。
s += 2;
不是在做你認為它在做的事情。 它將重載的+=
運算符調用到char
。 它不字符追加'2'
與值2,而是字符,結果將取決於你的平台上使用的編碼。
沒有定義運算符重載來允許s + 2
編譯1 。 因此錯誤。
在這兩種情況下的解決方案是使用std::to_string(2)
而不是int
文字 2。
1本質上的原因是因為operator+=
不是模板函數,而std::operator+
是,並且重載決議將有利於非模板函數而不是模板函數。
添加到string
的正確方法是
std::string s;
s += std::to_string(2);
s = s + std::to_string(2);
雖然@CoryKramer 的答案為您提供了向字符串添加整數的正確方法,但它並沒有解釋為什么指令s = s + 2
無法編譯。
兩條指令之間的區別在於,在第一條指令中,您使用std::string
的+= 運算符,而在第二條指令中,編譯器嘗試將2
轉換為字符串。
int
和std::string
之間沒有隱式轉換。 但是,您可以將int
為char
,這就是s += 2
起作用的原因。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.