我尝试了两种不同的方式将int
附加到std::string
,令我惊讶的是,我得到了不同的结果:
#include <string>
int main()
{
std::string s;
s += 2; // compiles correctly
s = s + 2; // compiler error
return 0;
}
为什么我在使用+=
运算符时编译并正常运行,但在使用+
运算符时失败?
我认为问题不像How to concatenate a std::string and an int?
在该问题中,没有答案使用+=
运算符。+=
之间的差异
而+
的{{1}}运算符是解决我疑问的关键。
坦率地说,这个问题是解释为什么c ++难以掌握的好例子。
答案 0 :(得分:46)
TL; DR operator+=
是class string
中的类成员函数,而operator+
是模板函数。
标准类template<typename CharT> basic_string<CharT>
重载了函数basic_string& operator+=(CharT)
,字符串只是basic_string<char>
。
由于适合较低类型的值可以自动转换为该类型,因此在表达式s += 2
中,2 不视为int
,但是{{1相反。它与<{1}}具有完全相同的效果。附加了带有ASCII码2(STX)的字符,不字符&#39; 2&#39; (ASCII值为50或0x32)。
但是,string没有像char
这样的重载成员函数,s += '\x02'
不是有效表达式,因此在编译期间会抛出错误。 (更多内容)
您可以通过以下方式在字符串中使用operator +函数:
string operator+(int)
对于关注为什么2不会被s + 2
自动转换为s = s + char(2); // or (char)2
s = s + std::string(2);
s = s + std::to_string(2); // C++11 and above only
的人,
char
以上是operator+
中plus运算符的原型 [note] ,因为它是模板函数,需要同时实现{{1}和template <typename CharT>
basic_string<CharT>
operator+(const basic_string<CharT>& lhs, CharT rhs);
,这是冲突的。有关详细信息,请参阅Why isn't automatic downcasting applied to template functions?
同时,s + 2
的原型是:
operator+<char>
你看,这里没有模板(它是一个类成员函数),所以编译器从类实现中推断出CharT是operator+<int>
类型,operator+=
自动转换为{{1} }}。
注意:从C ++标准包含源复制时,将删除不必要的代码。其中包括模板类&#34; basic_string&#34;的typename 2和3(Traits和Allocator),以及不必要的下划线,以提高可读性。
答案 1 :(得分:42)
+=
没有按照您的想法行事。它将重载的char
运算符调用为'2'
。它不附加字符 s + 2
,而是值 2的字符,结果将取决于编码。
没有定义运算符重载以允许std::to_string(2)
编译 1 。因此错误。
两种情况下的解决方案都是使用int
而不是operator+=
文字2。
1 基本上原因是因为std::operator+
不是模板函数,而{{1}}是,并且重载解析将支持非模板函数而非模板函数。
答案 2 :(得分:12)
添加到string
的正确方法是
std::string s;
s += std::to_string(2);
s = s + std::to_string(2);
答案 3 :(得分:2)
虽然@CoryKramer的答案为您提供了向字符串添加整数的正确方法,但它并不能解释为什么指令s = s + 2
无法编译。
两条指令之间的区别在于,在第一条指令中,您使用std::string
的{{3}},而在第二条指令中,编译器会尝试将2
转换为字符串。
int
和std::string
之间没有隐式转换。但是,您可以将int
投射到char
,这就是s += 2
有效的原因。