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

时间:2019-02-21 03:45:56

标签: c++ string debugging c-str

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


const author = {
        name: req.body.name
    }

AuthorModel.create(author, (error, createdAuthor)=>{
  //handle error

        BookModel.insertMany(req.body.books, function (err, createdbooks) {
            // handle error
            createdAuthor.books.push(createdbooks); 
            createdAuthor.save();
        })   
}

我的第一个观察结果是,当传递到#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()函数不会产生垃圾。我仍在尝试查看为什么在第一种情况下而不是第二种情况下失败。无论如何,分享这很有趣。

2 个答案:

答案 0 :(得分:3)

这是未定义的行为(UB),表示任何事情都可能发生,包括代码正常运行。 它是UB,因为emplace_back使向量中所有指向对象的指针无效。发生这种情况是因为可以重新分配向量(显然是这样)。

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

UB的第二种情况“有效”,因为字符串文本对于SSO而言太长并且驻留在独立的存储块上。在调整大小期间,会将字符串对象从其移开,从而将文本存储块的所有权移至新创建的字符串对象。由于内存块仅更改所有权,因此它在emplace_back之后仍然有效。

答案 1 :(得分:2)

std::string::c_str()

  

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


std::vector::emplace_back

  

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


由于在调用$(".class").append<option value="' +value.id+','+value.emp_type+ '"' + (+value.id+','+value.emp_type+ === lastSelectedEmpId ? 'selected="selected"' : '') + '>' + value.emp_name + '</option>; 时无法知道是否会发生vector重新分配,因此必须假设随后使用emplace_back中的较早返回值会导致未定义行为。

由于未定义行为是-未定义-可能发生任何事情。因此,您的代码似乎可以正常工作或失败。两种方式都出错。