""
是一个字符串字面值。它们的类型为N const char
的数组。这个特定的字符串字面值是一个1 const char
的数组,其唯一的元素是空终止符。
数组很容易衰变成指向它们第一个元素的指针,例如在需要指针的表达式中。
lhs + rhs
对于数组和整数不被定义为lhs
和rhs
。但是对于指针作为lhs和整数作为rhs,它是有定义的,具有通常的指针算术。
char
是C++核心语言中的一个整型数据类型(即将其视为整数)。
==> 因此,字符串字面值+
字符 被解释为 指针+
整数。
表达式"" + c
大致相当于:
static char const lit[1] = {'\0'};
char const* p = &lit[0];
p + c // "" + c is roughly equivalent to this expression
你返回一个 `std::string`。表达式 `"" + c` 产生一个指向常量字符的指针。期望一个 `const char*` 参数的 `std::string` 构造函数期望的是指向以 null 结尾的字符数组的指针。
如果 `c != 0`,那么表达式 `"" + c` 将导致未定义行为:
- 对于 `c > 1`,指针运算会产生未定义行为。指针运算只在数组上被定义,并且如果结果是同一数组的元素,则是安全的。
- 如果 `char` 是带符号类型,则对于相同的原因,`c < 0` 会产生未定义行为。
- 对于 `c == 1`,指针运算并不会产生未定义行为。这是一个特殊情况;指向数组最后一个元素之外的位置是允许的(尽管不能使用它所指向的内容)。尽管如此,仍会导致未定义行为,因为在这里调用的 `std::string` 构造函数要求其参数是指向有效数组(和以 null 结尾的字符串)的指针。而超出数组范围的那个元素并不属于该数组本身。违反这个要求同样导致未定义行为。
现在可能发生的情况是,`std::string` 的构造函数试图通过搜索与 '\0' 相等的数组中(第一个)字符来确定你传递给它的 null 结尾字符串的大小:
string(char const* p)
{
char const* end = p;
while(*end != '\0') ++end;
}
这将会导致访问冲突,或者所创建的字符串包含“垃圾”。
同时,编译器可能会认为这种未定义行为永远不会发生,并进行一些有趣的优化,导致出现奇怪的行为。
顺便说一下,clang++3.5对此片段发出了一个不错的警告:
警告:将'char'添加到字符串中不会将其附加到字符串[-Wstring-plus-int]
return "" + c; // Here
~~~^~~
注意: 使用数组索引来消除此警告
const char *str=""; return &(str[(int)c]);
。除非 C 是 0,否则会导致未定义行为。我的翻译保持了原文的意思并使其更易懂,但没有解释或提供额外的信息。 - hydes
字符串字面值感兴趣。 - Hiurareturn std::string(1, c);
来返回一个包含单个字符c
的std::string
对象。 - GingerPlusPlus