Big*_*lla 19 c++ string stdstring c++11
在下面的代码中
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a,c="!";
cin>>a;
int l=a.size();
for(int i=0;i<l;i++)
{
c=c+"#"+a[i];
}
cout<<c;
}
Run Code Online (Sandbox Code Playgroud)
如果我替换c=c+"#"+a[i]为c+="#"+a[i]我会得到意外的输出。第二种情况下的输出是 !boxboxboxbox 与https://www.onlinegdb.com/上的输入无关。在“dev c++”上,输出是 -
但是 a += b 等价于 a = a + b 。那么造成输出差异的原因是什么呢?
son*_*yao 23
给定c+="#"+a[i];,"#"+a[i]首先被评估。"#"是类型const char[2]并且可以衰减为指针 as const char*,a[i]是char整数类型的类型,然后"#"+a[i]只执行指针算术并且不会按照您的预期连接字符串。(并且指针运算的结果可能会超出数组的边界,然后导致 UB。)
在另一方面,在c=c+"#"+a[i];,c+"#"在第一被评估,其附加"#"上c并返回一个新的std::string(通过operator+对std::string),在其上a[i]被附加,并将结果指定给c。
但是 a += b 等价于 a = a + b
如果你把b集成,即加括号的("#"+a[i]),那么这两个c+=("#"+a[i]);并c=c+("#"+a[i]);产生同样的结果,即使它不是你所期望的。
由于c=c+"#"+a[i]表达式右侧的所有运算符都相同,因此表达式从左到右进行处理,第一个元素是 a,std::string向其添加 a创建const char*一个新元素,std::string然后添加一个char创建另一个元素std::string,最终分配给c。
与c+="#"+a[i]表达开始的与右const char*向其中添加一个char,这将调用指针算法产生一个无效的地址,然后将其附加到字符串c这是未定义的行为。要修复它,您必须强制第一个参数为 a std::string:c+=std::string("#")+a[i]
根本上是因为 C++ 以“带有类的 C”开始。多年来,添加了大量新功能并收紧了一些规则,但 C++ 作为扩展 C 的背景仍然清晰可见。特别是。
std::string (严格来说是 std::basic_string 模板,但让我们暂时忽略该细节)最好为您提供帮助。它为(再次忽略右值引用的细节)定义了合理的重载。
但它不能对两个参数都不是 std::string 的运算符做任何事情。它们在 C++ 中的工作方式与在 C 中的工作方式相同。
这样做的结果是操作顺序变得非常重要。
c=c+"#"+a[i];相当于c=((c+"#")+a[i]);。这很好用,在最内部的操作中,一个参数是 std::string,因此重载的运算符会做正确的事情并连接参数以生成另一个 std::string。当我们将最内层操作的结果连接到 a[i] 时,同样适用
c+="#"+a[i];在功能上等价于*,c=(c+("#"+a[i]));所以现在我们尝试在计算为 char * 的字符串文字和计算为 char 的操作之间使用 + 运算符。因此,我们将 a[i] 处的字符的字符代码添加到指向字符串“#”的指针。
由于“#”是一个相当短的字符串,这几乎肯定会导致指针超出字符串的末尾。这是语言规范未定义的行为。
我猜“!boxboxbox”是来自 onlinegdb 的沙箱错误。它检测到您的代码做了不该做的事情并拒绝让它继续。
许多编译器/链接器将不同的字符串数据放在一起,因此在常规编译器上显示(部分)来自可执行文件(或它使用的库)的另一个字符串可能是从字符串末尾运行的结果。
C++11 确实添加了对 std::string 文字的支持,因此一种解决方法可能是添加
using namespace std::string_literals;
然后"#"改为"#"s
* 请注意,一般来说,c++ 中的重载运算符“+”和“+=”是单独的运算符,没有什么会强制类的实现者使它们在功能上等效。理智的班级设计师通常会。
此外 += 可能更有效,因为它可能能够就地执行连接而不是创建新字符串。
| 归档时间: |
|
| 查看次数: |
1044 次 |
| 最近记录: |