c++ - C ++:为什么这个字符串输入失败而另一个没有
问题描述
我从朋友那里得到了这个问题
#include <string>
#include <vector>
#include <iostream>
void riddle(std::string input)
{
auto strings = std::vector<std::string>{};
strings.push_back(input);
auto raw = strings[0].c_str();
strings.emplace_back("dummy");
std::cout << raw << "\n";
}
int main()
{
riddle("Hello world of!"); // Why does this print garbage?
//riddle("Always look at the bright side of life!"); // And why doesn't this?
std::cin.get();
}
我的第一个观察是,当传入的单词数超过 3 个单词riddle()
时,该函数不会产生垃圾。input
我仍在试图了解为什么它在第一种情况下失败,而不是在第二种情况下。不管怎样,我觉得分享这个很有趣。
解决方案
这是未定义的行为 (UB),这意味着任何事情都可能发生,包括代码工作。它是 UB,因为它emplace_back
使指向向量中对象的所有指针无效。发生这种情况是因为向量可能会被重新分配(显然是这样)。
由于短字符串优化 (sso),UB 的第一种情况“不起作用”。由于sso,原始指针指向向量直接分配的内存,重新分配后丢失。
UB 的第二种情况“有效”,因为字符串文本对于 SSO 来说太长并且驻留在独立的内存块上。在调整大小期间,字符串对象被移动,将文本内存块的所有权移动到新创建的字符串对象。由于内存块只是更改所有权,它在emplace_back
.
推荐阅读
- java - Java数组排序单词仅从列表中打印两个
- javascript - 双击 c3js 折线图
- amazon-redshift - 如何授予用户对系统表的有限访问权限?
- java - Braintree 集成 - 错误:找不到类:com.braintreepayments.api.dropin.DropInRequest
- php - 如何向新用户发送重置密码的通知
- java - Java 是否允许将 getter 作为方法参数传递?
- powerbi - 使用 Power BI 中的度量动态筛选列
- javascript - 尝试将 Dom 添加到 chrome-extension:// URL 时无法访问页面内容
- ios - 构建 iOS 框架时未找到 Ktor 和 kotlinx 依赖项
- vmware-clarity - 切换选项卡时模型值丢失