为什么name
在以下 C++ 代码中行为不端?
string name = "ab"+'c';
等效代码在 Java/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:strings 允许您按预期将字符附加到它们:
std::string foo = "012345678910121416182022242628303234";
std::string name = foo + ' ';
name
设置为“012345678910121416182022242628303234”
问题是“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)
which 连接,但编译器甚至不会查找它,因为第一个参数不是 std::string。
所以一个解决方案是手动创建字符串:
string name = std::string("ab")+'c';
现在编译器可以找出正确的 operator+ 来调用。
在 C++ 中,编译器正在寻找具有此原型的函数:
T operator+ (const char*, char);
由于没有,它无法弄清楚 T 是什么并且无法解析operator<<
调用,所以它回退到唯一剩下的解决方案:指针加法。像 Josh 的回答那样连接到字符串没有问题,因为它存在一个函数。
给定 C++ 代码:
std::string name = "ab"+'c';
Java中的等价物是:
String name = "ab".substring('c');
两者都将 char 提升为 int。当然,在 Java 中,它会进行范围检查,因此会引发异常。在 C++ 中,您只会得到未定义的行为(或类似行为)。
爪哇:
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# 中连接字符串和字符 - 我猜它不像 C++ 那样严格。
这在 C# 中工作得很好:
string test = "foo" + 'b';
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++ 中做的是
字符串名称 = string("ab") +'c';
请记住,文字“ab”不是字符串类型。您所做的是希望在 char 数组和字符之间没有“+”,然后希望编译器能够以某种方式注意到您确实希望结果是 std::string,然后解析您的表达式右侧是一些隐式转换的组合,可以与运算符组合以产生该类型的结果。对我来说似乎是一个相当高的要求。
不管怎样,没关系。你看,在 C 中,数组和指针之间的唯一区别是它们的内存是如何分配的。一旦你有了一个,你基本上就有了一个“数组/指针的东西”。因此,“+”是在所有数组和指针上定义的运算符,它接受任何整数类型的另一个参数并进行指针数学运算,返回指向该点之后那么多元素的指针。此外,在 C 中,“char”实际上只是另一种整数类型。这些 C 设计决策都是有用的hack,但正如 hack 经常发生的那样,它们结合了直观意想不到的结果。因此,所有 "ab" + 'c' 为您所做的就是返回一个地址 99 个字节,只要 "ab" 文字恰好存储在内存中。
有时您可以依赖隐式转换,但您确实必须准备好在其他时候帮助您的编译器。