为什么以下C++代码中的name
表现异常?
string name = "ab"+'c';
在Java/C#中,等效代码会表现出怎样的行为?
为什么以下C++代码中的name
表现异常?
string name = "ab"+'c';
尝试
std::string name = "ab" "c";
或者std::string name = std::string("ab") + c;
在C++中,"ab"不是一个std::string
,而是指向一串字符的指针。当你将一个整数值添加到指针上时,你会得到一个新的指针,它指向更远的字符串:
char *foo = "012345678910121416182022242628303234";
std::string name = foo + ' ';
name
被设置为"3234",因为' '的整数值为32,而'foo'的开头到其32个字符刚好在字符串结尾的前四个字符处。如果字符串较短,则会尝试访问未定义内存区域。
解决方案是将字符数组转换为std:string。std:string允许您像预期的那样附加字符:
std::string foo = "012345678910121416182022242628303234";
std::string name = foo + ' ';
name
被设置为"012345678910121416182022242628303234 "
string name = std::string("ab")+'c';
T operator+ (const char*, char);
由于没有声明 T,编译器无法确定 T 的类型并且不能解析 operator<< 调用,因此只能退而求其次:指针相加。像 Josh 回答中所示,将字符串连接起来没有问题,因为有函数可用。
给定以下C++代码:
std::string name = "ab"+'c';
String name = "ab".substring('c');
两者都将char类型转换为int类型。当然在Java中,它会进行范围检查并因此引发异常。在C ++中,您只会得到未定义的行为(或类似的)。
Java:
public class Main
{
public static void main(String[] args)
{
System.out.println("AB" + 'c');
}
}
输出结果为:
ABc
编辑:
实际上,编译器硬编码了字符串ABc...
如果你使用“AB”+argv[0].charAt(0)来使用一个变量,那么编译器会这样做(基本上是):
StringBuilder b = new StringBuilder;
b.append("AB");
b.append(argv[0].charAt(0));
System.out.println(b.toString());
C++编译器不会自动将字符串字面值与字符字面值连接起来。但它会将字符串字面值彼此连接起来。语法如下:
const char * cs = "ab" "c"; // append string-literals
string
不是C++语言中的一个内置类型。但是,在C++标准库中有一个string
类型。以下是一些使用示例:#include <string>
const char * cs = "ab" "c";
std::string s1( cs );
std::string s2( "ab" "c" );
std::string s3 = "ab" "c";
在C#中,您可以连接字符串和字符 - 我想它不像C++那么严格。
这在C#中完全正常:
string test = "foo" + 'b';
嗯,通常我在C++中会这样做:
string name = string("ab") + 'c';
记住,字面量"ab"并不是string类型。你所做的是希望char数组和字符之间没有"+"运算符可用,并且希望编译器能够注意到你真正想要的结果是std::string类型,并且解析右侧表达式以找到一些隐式转换的组合,可以与运算符结合产生该类型的结果。对我来说,这似乎是一个相当高的要求。
无论如何,这都无关紧要。你看,在C语言中,数组和指针之间唯一的区别就是它们的内存分配方式。一旦你有了其中一个,你基本上就拥有了一个"数组/指针的东西"。因此,"+"是定义在所有数组和指针上的运算符,它接受另一个任意整数类型的参数,并进行指针运算,返回指向那个位置后面那么多元素的指针。此外,在C语言中,"char"实际上只是另一种整数类型。这些C语言的设计决策都是有用的"技巧",但常常与直觉上意想不到的结果结合在一起。所以,"ab" + 'c' 对你来说只是返回一个地址,该地址在内存中距离"ab"字面量存储的位置99个字节。
有时您可以依赖于隐式转换,但在其他情况下,您真的必须准备好为编译器提供一些帮助。