添加这些字符串有什么区别?
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";
- 计算第一个加法参数
- 右边是字符数组:
const char[3]
- 左边有
char
可以自动转换为int
const char[3]
降级为 const char *
- 添加
int
(97
) 和 const char *
是可行的,但结果超出了缓冲区范围。
- 那么您正在使用
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++ 中,char
s 只是小整数。所以 '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";
char
和 char *
类型的 class std::string 和 objects 使用了重载运算符 +=
。所以这些语句是 well-defined.
请注意,您应该明确包含 header <string>
。
#include <string>
程序 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";
- 计算第一个加法参数
- 右边是字符数组:
const char[3]
- 左边有
char
可以自动转换为int
const char[3]
降级为const char *
- 添加
int
(97
) 和const char *
是可行的,但结果超出了缓冲区范围。 - 那么您正在使用
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++ 中,char
s 只是小整数。所以 '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";
char
和 char *
类型的 class std::string 和 objects 使用了重载运算符 +=
。所以这些语句是 well-defined.
请注意,您应该明确包含 header <string>
。
#include <string>