我注意到,当我初始化一个字符串时,编译器报告了一个我没想到的错误.
例如:
#include <iostream> #include <string> using namespace std; int main() { string s1 = "Hello",s2 = "World!"; // ok string s3 = s1 + "," + "World!"; // ok string s4 = "Hello" + "," + s2; // error cout << s1 + " " + s2 << endl; //ok return 0; }
对我来说,如果s3工作正常,s4也应该这样做.
为什么我会收到这个错误?这两个初始化字符串(s3和s4)之间有什么区别?
解决方法
“Hello”不是std :: string(而是它是一个const char [6],而“,”是一个const char [3])并且std :: strings的运算符不适用.
这是C的一个小小的不便,源于它的C系列.这意味着在连接字符串时必须确保它的两个操作数中至少有一个实际上是一个std :: string,如
auto s = std::string{"Hello"} + "," + "World";
其中第一个有一个std :: string作为它的第一个操作数,因此产生一个std :: string,所以第二个也有一个std :: string作为它的第一个操作数(因为从左到右处理).
由T.C.的注释提示的Edit1,我提到如果只用空格分隔,C字符串文字会自动连接:
std::string s = "Hello" "," "World";
此行为也是从C继承的:预处理器将上面的代码呈现给
std::string s = "Hello,World";
在编译器正确处理它之前(更准确地说,字符串连接发生在翻译的phase 6,就在编译之前).这实际上是连接原始字符串文字的最简单,也是最方便的方法.但请注意,我必须声明s的类型,因为自动推断会给出一个const char *.
在PaperBirdMaster评论提示的Edit2中,我提到自从C 14以来,如果你拉入相关的operator""s
(或周围的命名空间),你可以直接在字符串之后添加s来直接形成std :: string文字.
using std::literals::operator""s; // pull in required operator const auto s = "Hello"s + "," + "World"; // std::string
请参阅this post,了解为什么必需的运算符“”隐藏在嵌套的命名空间中.另请注意,使用std :: literals :: operator“”;你可以拉入周围的命名空间:以下任何一个声明都可以.
using namespace std::string_literals; using namespace std::literals::string_literals; using namespace std::literals;
使用命名空间std;并没有那么糟糕(和该死)