我注意到当我初始化一个字符串时,编译器报告了一个我没有预料到的错误。
例如:
#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::string
的 +
运算符不适用。
这是 C++ 的一个小不便,源于它的 C 血统。这意味着在通过 +
连接字符串时,您必须确保其两个操作数中至少有一个实际上是 std::string
,如
auto s = std::string{"Hello"} + ", " + "World";
其中第一个 +
有一个 std::string
作为它的第一个操作数,因此产生一个 std::string
,所以第二个 +
也有一个 std::string
作为它的第一个操作数(因为 +
是从左到右处理的)。
Edit1 由 T.C. 的评论提示,我提到如果仅用空格分隔,C 字符串文字会自动连接:
std::string s = "Hello" ", " "World";
这个行为也是从 C 继承而来的:预处理器将上面的代码呈现给
std::string s = "Hello, World";
在编译器正确处理它之前(更准确地说,字符串连接发生在翻译的 phase 6 中,就在编译之前)。这实际上是连接原始字符串文字的最简单因此也是最方便的方法。但请注意,我必须声明 s
的类型,因为 auto
推导会给出 const char*
。
Edit2 由 PaperBirdMaster 的评论提示,我提到自 C++14 起,您可以通过简单地在字符串后添加 s
直接形成 std::string
文字,如果您拉入相关的operator""s
(或周围的命名空间)。
using std::literals::operator""s; // pull in required operator
const auto s = "Hello"s + ", " + "World"; // std::string
参见 this post至于为什么所需的 operator""s
隐藏在嵌套的命名空间中。另请注意,除了 using std::literals::operator""s;
之外,您还可以引入周围的 namespace
:以下任一声明都可以。
using namespace std::string_literals;
using namespace std::literals::string_literals;
using namespace std::literals;
这不像普通的 using namespace std;
那样糟糕(而且该死)。
关于c++ - 这两种添加字符串的情况有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32555142/