为什么name
在以下C ++代码中出错?
string name = "ab"+'c';
等效代码在Java / C#中的表现如何?
答案 0 :(得分:13)
尝试
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:strings允许您按预期将字符附加到它们:
std::string foo = "012345678910121416182022242628303234";
std::string name = foo + ' ';
name
设置为“012345678910121416182022242628303234”
答案 1 :(得分:8)
问题是“ab”不是C ++ std::string
,而是const char[3]
。
所以它正在寻找的+运算符是operator+ (const char[3], char)
。这不存在,因此编译器会尝试让数组衰减到指针,因此它会查找operator+ (const char*, char)
。这是存在的,所以编译器会选择它,但它做错了。将一个整数值(char)添加到指针(const char *)是一个很常见的操作,显然,这就是这个operator +的作用。理解这一点的关键是要意识到第一个参数是1)一个数组,2)每当数组没有意义时的指针。它在C中也被用作字符串,是的,但它不是字符串。它是一个指针(或偶尔,一个数组)。
有operator+ (const std::string&, char)
连接,但编译器甚至不会查找它,因为第一个参数不是std :: string。
所以解决方案是手动创建字符串:
string name = std::string("ab")+'c';
现在编译器可以找出正确的operator +来调用。
答案 2 :(得分:5)
在C ++中,编译器正在寻找具有此原型的函数:
T operator+ (const char*, char);
由于没有一个,它无法弄清楚T是什么并且无法解析operator<<
调用,因此它回退到唯一的解决方案:指针添加。在Josh的答案中连接到字符串没有问题,因为它存在一个函数。
答案 3 :(得分:3)
给出C ++代码:
std::string name = "ab"+'c';
Java中的等价物是:
String name = "ab".substring('c');
两者都将char提升为int。当然在Java中,它会进行范围检查,因此会引发异常。在C ++中,你只是得到了未定义的行为(或者某些)。
答案 4 :(得分:2)
Java:
public class Main
{
public static void main(String[] args)
{
System.out.println("AB" + 'c');
}
}
输出是:
ABC
编辑:
实际上编译器硬编码String ABc ...
如果你做“AB”+ argv [0] .charAt(0);为了使它使用变量然后编译器执行此操作(基本上):
StringBuilder b = new StringBuilder;
b.append("AB");
b.append(argv[0].charAt(0));
System.out.println(b.toString());
答案 5 :(得分:1)
你可以在C#中连接字符串和字符 - 它不像C ++那么严格。
这在C#中运行得很好:
string test = "foo" + 'b';
答案 6 :(得分:1)
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";
答案 7 :(得分:1)
嗯,我通常在C ++中会做的是
string name = string(“ab”)+'c';
请记住,文字“ab”是不是类型字符串。你正在做的是希望char数组和字符之间没有“+”,然后希望编译器能以某种方式注意到你真的希望结果是一个std :: string,然后解析你的表达式隐式转换的某些组合的右侧,可以与运算符组合以生成该类型的结果。对我来说似乎是一个相当高的命令。
无论如何,没关系。你会看到,在C中,数组和指针之间的唯一区别是它们的内存是如何分配的。一旦你有一个,你基本上有一个“数组/指针的东西”。因此,“+”是在所有数组和指针上定义的运算符,它接受任何整数类型的另一个参数并执行指针数学运算,返回指向该点之后的许多元素的指针。另外,在C“char”中实际上只是另一种整数类型。这些C设计决策都是有用的 hacks ,但与黑客经常发生的情况一样,它们与直观的意外结果相结合。因此,所有“ab”+“c”为你做的是返回99字节的地址,而“ab”字面值恰好存储在内存中。
有时你可以依赖隐式转换,但你真的必须准备好在其他时候帮助你的编译器。