C++ C++;:为什么这个字符串输入失败而另一个没有

C++ C++;:为什么这个字符串输入失败而另一个没有,c++,string,debugging,c-str,C++,String,Debugging,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(); stri

我从一个朋友那里得到这个问题

#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();
}
#包括
#包括
#包括
无效谜语(标准::字符串输入)
{
自动字符串=std::vector{};
字符串。推回(输入);
自动原始=字符串[0]。c_str();
字符串。放回(“虚拟”);

这是未定义的行为(UB),意味着任何事情都可能发生,包括代码工作。 这是因为
emplace\u back
会使向量中对象的所有指针无效。这是因为向量可能被重新分配(显然是这样的)

由于短字符串优化(sso),UB的第一种情况“不起作用”。由于sso,原始指针指向向量直接分配的内存,该内存在重新分配后丢失


UB“工作”的第二个案例因为字符串文本对于SSO来说太长,并且驻留在一个独立的内存块上。在调整字符串对象大小的过程中,字符串对象从移动,将文本的内存块的所有权移动到新创建的字符串对象。由于内存块只是更改所有权,因此在
重新放置后它仍然有效

这是未定义的d行为(UB),意味着任何事情都可能发生,包括代码工作。 这是因为
emplace\u back
会使向量中对象的所有指针无效。这是因为向量可能被重新分配(显然是这样的)

由于短字符串优化(sso),UB的第一种情况“不起作用”。由于sso,原始指针指向向量直接分配的内存,该内存在重新分配后丢失

UB“工作”的第二个案例因为字符串文本对于SSO来说太长,并且驻留在一个独立的内存块上。在调整字符串对象大小的过程中,字符串对象从移动,将文本内存块的所有权移动到新创建的字符串对象。由于内存块只会更改所有权,因此它在放置回后仍然有效

对修改对象的其他成员函数的进一步调用可能会使返回的指针无效


:

如果发生重新分配,将修改所有包含的元素


由于在调用
emplace\u back
时无法知道是否会发生
vector
重新分配,因此您必须假设后续使用
string::c\u str()
中较早的返回值会导致未定义的行为

由于未定义的行为是-未定义的-任何事情都可能发生。因此,您的代码可能看起来正常工作,也可能失败。无论哪种方式都是错误的。

:

对修改对象的其他成员函数的进一步调用可能会使返回的指针无效


:

如果发生重新分配,将修改所有包含的元素


由于在调用
emplace\u back
时无法知道是否会发生
vector
重新分配,因此您必须假设后续使用
string::c\u str()
中较早的返回值会导致未定义的行为


由于未定义的行为是-未定义的-任何事情都可能发生。因此,您的代码可能看起来有效,也可能失败。这两种情况都是错误的。

调用
emplace\u back
会导致向量的重新分配。它可能适用于第二种情况,而不是第一种情况,因为第一个字符串使用SSO,而第二个字符串不使用SSO。您应该ldn不依赖于这种行为。@0x499602D2我明白了,为什么安放_back()第一种情况下失败,而第二种情况下失败?调用
emplace_back
会导致向量的重新分配。它可能适用于第二种情况,而不是第一种情况,因为第一个字符串使用SSO,而第二个字符串不使用。但您不应该依赖此行为。@0x499602D2我明白了为什么emplace_back()第一个案例失败,但第二个案例失败?