添加这些字符串有什么区别?

What is the difference between adding these strings?

程序 1:

#include <iostream>
using namespace std;

int main() {
    string str;
    char temp = 'a';
    str += temp + "bc";
    cout << str;
    return 0;
}

输出:

未知字符

程序 2:

#include <iostream>
using namespace std;

int main() {
    string str;
    char temp = 'a';
    str += temp;
    str += "bc";
    cout << str;
    return 0;
}

输出:

abc

为什么两个输出不同?两个输出不应该相同吗?

这一行中的程序 1

str += temp + "bc";
  1. 计算第一个加法参数
  2. 右边是字符数组:const char[3]
  3. 左边有char可以自动转换为int
  4. const char[3] 降级为 const char *
  5. 添加 int (97) 和 const char * 是可行的,但结果超出了缓冲区范围。
  6. 那么您正在使用 basic_string::operator+=( const CharT* s );,但参数无效。你有缓冲区溢出。

计划 2。 没有这种未定义的行为,并且使用 std::string 形式的运算符。

另一个合理的版本是:

str = str + temp + "bc";

现在每次添加都会创建一个 std::string 作为结果。

std::string class 重载了 ++= 运算符,允许您使用它们将 std::string 与其他字符连接起来和字符数组。

但是就像在 C 中一样,"bc" 不是 std::string 而是 const char [3](3 个字符的常量数组)。数组通常会自动转换 (decay) 为指向其第一个元素的指针。这里也有。

str += "foobar"; 一个接一个地追加指针指向的字符,直到遇到终止字符串的空字节。

您可以将整数添加到指针:str += "foobar" + 3; 会将 "bar" 附加到字符串。

在 C++ 中,chars 只是小整数。所以 'a' + "bc" 实际上意味着 97 + "bs" (假设你的编译器使用 ASCII,所有常见的都使用)。

这形成了一个超出数组范围的指针,并导致未定义的行为。

您看到的随机字符是位于 "bc" 数组后 97 个字节的内存内容,以该内存中的随机空字节终止。

此声明

str += temp + "bc";

可以表示为

str = str + ( temp + "bc" );

在 sub-expression temp + "bc" 中,字符串文字 "bc" 被隐式转换为指向其第一个字符的指针,类型为 const char *。由于整数提升,变量 temp 的值被转换为整数类型,例如在 ASCII table 中具有值 97.

所以在sub-expression中使用了指针运算。表达式 temp + "bc" 指向字符串文字之外的内存。所以表达式的结果是未定义的。

如果你会写,例如

char temp = 1;

则表达式 temp + "bc" 指向字符串文字的第二个字符。结果 str 的值为 'b'.

或者要获得与您编写的第二个程序相同的结果

str += temp + std::string( "bc" );

至于第二个程序则在此声明

str += temp;
str += "bc";

charchar * 类型的 class std::string 和 objects 使用了重载运算符 +=。所以这些语句是 well-defined.

请注意,您应该明确包含 header <string>

#include <string>