std::string assign,clear和operator[]的奇怪行为
strange behavior of std::string assign,clear and operator[]
我观察到字符串操作的一些奇怪行为。
,
int main()
{
std::string name("ABCDEFGHIJ");
std::cout << "Hello, " << name << "!n";
name.clear();
std::cout << "Hello, " << name << "!n";
name.assign("ABCDEF",6);
std::cout << "Hello, " << name << "!n";
std::cout << "Hello, " << name[8] << "!n";
}
输出:Hello, ABCDEFGHIJ!
Hello, !
Hello, ABCDEF!
Hello, I!
string::clear实际上没有清除,因为即使在清除之后我也能够访问数据。根据文档,当我们访问超出边界的东西时,结果是未定义的。但这里我每次都得到相同的结果。谁能解释一下当我们调用clear或operator [].
欢迎来到c++的神奇魅力——"未定义行为"。
当name
包含6个字符的字符串"ABCDEF"时,name[8]
尝试访问字符串中不存在的成员,这是未定义行为。
这意味着该操作的结果完全没有意义。
c++标准没有定义访问字符串中不存在的成员字符的结果;因此出现了未定义的行为。该操作的潜在结果可能是:
字符串中给定位置的先前值
一些垃圾,随机字符
程序崩溃
。
每次执行程序的结果都不一样,从选项1到4中选择。
name.assign("六边形ABCDEF",6);
现在字符串的长度为6。因此,只能合法地访问0到5号元素。
std:: cout & lt; & lt;"你好"<<名称[8]& lt; & lt;"! n";
因此这是未定义行为。编译器可以自由地做任何它想做的事。不仅仅是语句,还包括整个程序,甚至包括前面的行!
此时,它返回先前位于该位置的字符。它可以返回其他任何东西,它可以崩溃,它可以完全跳过那个语句,它可以跳过赋值和许多其他有趣的事情(包括使守护进程从你的鼻子里飞出来!)。我这么说是因为所有这些行为(除了守护进程)实际上都可以在各种情况下在野外观察到。
正如其他人所说,访问std::string
之外的逻辑边界(即[0,size()],注意包括size())是未定义的行为,因此编译器可以使任何事情发生。
现在,你所看到的UB的特殊味道并没有什么特别意外的。
clear()
只是将字符串的逻辑长度归零,但是它所使用的内存被保留(这实际上是标准所要求的,如果没有这种行为,相当多的代码将工作得更慢)。
考虑到没有理由浪费时间将旧数据归零,通过越界访问字符串,您可以看到该索引之前的内容。
如果你在clear()
之后调用shrink_to_fit()
方法,这可能会改变,它要求字符串释放它保留的所有额外内存。
我想添加到其他答案中,您可以使用std::string::at
而不是使用operator[]
。
std::string::at
进行边界检查,当您试图访问超出范围的元素时,将抛出std::out_of_range
。
我通过调试器运行了您的代码。注意字符串的容量。仍然是15。"assign"没有改变容量。所以你不会得到每个人都说的"垃圾"价值。你得到的是完全相同的数据存储在相同的位置。如前所述,字符串只是一个指向内存地址的指针。它将通过x字节来访问元素。Name[8]是一个常量值,它将到完全相同的内存位置。这是调试器
- C++ 使用 assign 函数的字符串与直接使用 '=' 更改值的字符串之间的区别
- 集合上的输出迭代器:assign和increment迭代器
- 为什么 std::optional::operator=(U&&) 要求你是非标量类型?
- 'operator='已弃用:改用 QDir::setPath()
- 过载'operator new'如何导致无限循环?
- 'string.assign(string.data(), 5)' 是明确定义的还是 UB?
- 与'operator='不匹配(操作数类型'String'且"void")
- SegFault 同时使用 std::string::operator+= 和函数作为参数
- 处理"no operator found"
- 如何编写 operator= 用于使用虚拟方法与非平凡成员的匿名联合
- 运算符重载:"operator+"必须采用零个或一个参数
- 使用 operator() 扩展 Eigen::EigenBase
- 错误消息:使用"string* +="后"no match for 'operator+='"
- 有没有办法修改'operator->',以便'z->im'返回复数的虚部
- "operator +="行为异常的定义
- C++ "error: use of overloaded operator '*' is ambiguous"似乎只有一场比赛
- 错误:二进制'operator*' 'float'和'float[0]'类型的操作数无效
- std::vector::assign/std::vector::operator=(const&) 是否保证在"this"中重用缓冲区?
- operator=使用move assign和pass by value copy assign的歧义重载
- std::string assign,clear和operator[]的奇怪行为