C++:为什么这个字符串输入失败而另一个没有
C++: Why does this string input fail while the other does not
我从朋友那里得到了这个问题
#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();
}
我的第一个观察是,当传入input
的字数超过3个字时,riddle()
函数不会产生垃圾。我仍在尝试了解为什么第一种情况失败而不是第二种情况。不管怎样,我觉得分享这件事很有趣。
这是未定义的行为 (UB),意味着任何事情都可能发生,包括代码工作。
它是 UB,因为 emplace_back
使指向向量中对象的所有指针无效。发生这种情况是因为向量可能会被重新分配(显然是这样)。
UB第一例"doesn't work"因为短字符串优化(sso)。由于sso,原始指针指向vector直接分配的内存,重新分配后丢失。
UB的第二种情况"works"因为字符串文本对于SSO来说太长,驻留在一个独立的内存块上。在调整大小时,字符串对象被移动,将文本内存块的所有权移动到新创建的字符串对象。由于内存块只是改变了所有权,它在 emplace_back
.
之后仍然有效
The pointer returned may be invalidated by further calls to other member functions that modify the object.
If a reallocation happens, all contained elements are modified.
由于无法知道在调用 emplace_back
时是否会发生 vector
重新分配,因此您必须假设随后使用来自 string::c_str()
导致未定义的行为。
由于未定义的行为是 - 未定义的 - 任何事情都可能发生。因此,您的代码可能看起来有效,也可能看起来失败。无论如何都是错误的。
我从朋友那里得到了这个问题
#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();
}
我的第一个观察是,当传入input
的字数超过3个字时,riddle()
函数不会产生垃圾。我仍在尝试了解为什么第一种情况失败而不是第二种情况。不管怎样,我觉得分享这件事很有趣。
这是未定义的行为 (UB),意味着任何事情都可能发生,包括代码工作。
它是 UB,因为 emplace_back
使指向向量中对象的所有指针无效。发生这种情况是因为向量可能会被重新分配(显然是这样)。
UB第一例"doesn't work"因为短字符串优化(sso)。由于sso,原始指针指向vector直接分配的内存,重新分配后丢失。
UB的第二种情况"works"因为字符串文本对于SSO来说太长,驻留在一个独立的内存块上。在调整大小时,字符串对象被移动,将文本内存块的所有权移动到新创建的字符串对象。由于内存块只是改变了所有权,它在 emplace_back
.
The pointer returned may be invalidated by further calls to other member functions that modify the object.
If a reallocation happens, all contained elements are modified.
由于无法知道在调用 emplace_back
时是否会发生 vector
重新分配,因此您必须假设随后使用来自 string::c_str()
导致未定义的行为。
由于未定义的行为是 - 未定义的 - 任何事情都可能发生。因此,您的代码可能看起来有效,也可能看起来失败。无论如何都是错误的。