首页 > 解决方案 > 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我仍在试图了解为什么它在第一种情况下失败,而不是在第二种情况下。不管怎样,我觉得分享这个很有趣。

标签: c++stringdebuggingc-str

解决方案


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

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

UB 的第二种情况“有效”,因为字符串文本对于 SSO 来说太长并且驻留在独立的内存块上。在调整大小期间,字符串对象被移动,将文本内存块的所有权移动到新创建的字符串对象。由于内存块只是更改所有权,它在emplace_back.


推荐阅读