我注意到,当我初始化一个字符串时,编译器报告了一个我没想到的错误.
例如:
#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;
}
Run Code Online (Sandbox Code Playgroud)
对我来说,如果s3工作得很好,也s4应该这样做.
为什么我会收到这个错误?这两个初始化字符串(s3和s4)有什么区别?
Wal*_*ter 13
"Hello"不是a std::string(而是a const char[6],而", "a是a const char[3])并且s 的+运算符std::string不适用.
这是C++的一个小小的不便,源于它的C系列.这意味着在通过连接字符串+时必须确保其两个操作数中的至少一个实际上是a std::string,如
auto s = std::string{"Hello"} + ", " + "World";
Run Code Online (Sandbox Code Playgroud)
其中第一个+有一个std::string作为它的第一个操作数,因此产生一个std::string,所以第二个+也有一个std::string作为它的第一个操作数(因为+从左到右处理).
TC的注释提示Edit1,我提到如果只用空格分隔,C字符串文字会自动连接:
std::string s = "Hello" ", " "World";
Run Code Online (Sandbox Code Playgroud)
此行为也是从C继承的:预处理器将上面的代码呈现给
std::string s = "Hello, World";
Run Code Online (Sandbox Code Playgroud)
在编译器正确处理它之前(更准确地说,字符串连接发生在转换的第6阶段,就在编译之前).这实际上是连接原始字符串文字的最简单,也是最方便的方法.但请注意,我必须声明类型s,因为auto扣除会给出一个const char*.
由PaperBirdMaster的评论提示Edit2,我提到自从C++ 14以来,如果你拉入相关的(或周围的命名空间),你可以std::string通过简单地s在字符串之后添加来直接形成文字.operator""s
using std::literals::operator""s; // pull in required operator
const auto s = "Hello"s + ", " + "World"; // std::string
Run Code Online (Sandbox Code Playgroud)
请参阅这篇文章,了解为什么需要operator""s隐藏在嵌套命名空间中.另请注意,using std::literals::operator""s;您可以选择拉入周围namespace:以下任一声明都可以.
using namespace std::string_literals;
using namespace std::literals::string_literals;
using namespace std::literals;
Run Code Online (Sandbox Code Playgroud)
这并不像平原那样糟糕(和该死)using namespace std;.
以下行尝试将2个指针添加到一起.
string s4 = "Hello" + ", " + s2; // error
Run Code Online (Sandbox Code Playgroud)
"Hello"是const char[6]衰变的const char*,", "是char[3]衰变的常数const char*.
您正在尝试为a分配两个指针std::string,这是无效的.此外,添加两个指针也无效.
正如其他人说,这并没有什么关系的重载operator+的的std::string类,如下面的代码也无法编译出于同样的原因:
string s4 = "Hello" + ", ";
Run Code Online (Sandbox Code Playgroud)
我添加了一些用户@dyp提供的说明.
您可以使用C++标准库"用户定义的"字符串文字来解决您的问题.提供的功能可std::literals::string_literals::operator""s在<string>标题中找到.您可能必须使用using-directive或-declaration; 我的编译器不需要这个,包括<string>标题就足够了.例:
string s4 = "Hello"s + ", "s + s2;
Run Code Online (Sandbox Code Playgroud)
这相当于:
string s4 = std::string("Hello") + std::string(", ") + s2;
Run Code Online (Sandbox Code Playgroud)
当您将实例std::string作为第一个操作数放置时,表达式的其余部分将使用该类型,因为operator +的从左到右的关联性将确保std::string每次都返回一个实例作为最左侧的操作数,而不是const char*.这就是为什么你没有在线错误:
string s3 = s1 + ", " + "World!";
Run Code Online (Sandbox Code Playgroud)
该行相当于:
string s3 = ((s1 + ", ") + "World!");
Run Code Online (Sandbox Code Playgroud)
在C++中,字符串通常表示为具有类型std::string的C或字符串char[N],其中N是C字符串中的字符数加上终止字符(或空字符)中的字符数\0.
当通过一个字符串文字作为,例如,"Hello"一个功能时,实际上是传递char[6],这将衰减到一个指针char*,如C++不允许通过值传递数组.此外,C++并没有允许非const指针字符串文字,因此,参数类型必须成为const char*.
std::string具有二进制加法运算符的现有重载,允许您将两个std::string对象连接成一个,以及将std::string对象与C字符串连接.
std::string s1 = "Hello";
std::string s2 = "World";
// Uses 'std::string operator+(const std::string&, const std::string&)'.
std::string s3 = s1 + s2;
// Uses 'std::string operator+(const std::string&, const char*)'.
std::string s4 = s1 + "World";
// Also ok.
std::string s4 = "Hello" + s2;
Run Code Online (Sandbox Code Playgroud)
但是,连接两个C字符串没有过载.
// Error. No overload for 'std::string operator+(const char*, const char*)' found.
std::string s5 = "Hello" + "World";
Run Code Online (Sandbox Code Playgroud)
在C++中从左到右执行添加,因此,长连接表达式需要从std::string对象开始.
std::string s6 = "Hello" + ", " + s2; // Error. Addition is performed left-to-right and
// you can't concatenate two C-strings.
std::string s7 = s1 + ", " + "World"; // Ok. 's1 + ", "' returns a new temporary
// 'std::string' object that "World" is concat'ed to.
Run Code Online (Sandbox Code Playgroud)
使用C++ 14 标准文字,您可以std::string从文字表达式创建对象(请注意文字表达式中的尾部s).
using namespace std::literals;
std::string s8 = "Hello"s + ", " + "World"; // Ok
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用预处理器将自动连接用空格分隔的文字字符串这一事实.
std::string s9 = "Hello" ", " "World"; // Ok
Run Code Online (Sandbox Code Playgroud)
但是,你也可以完全跳过空格并使用单个字符串文字.
| 归档时间: |
|
| 查看次数: |
277 次 |
| 最近记录: |