【发布时间】:2020-12-20 12:14:06
【问题描述】:
我今天遇到了这个简单的代码。
#include <iostream>
#include <string>
#include <string_view>
#include <unordered_map>
#include <vector>
int main(int argc, char* argv[]) {
std::unordered_map<std::string, int> m = {
{"asdf", 123},
{"dsdfesjfdaslkfjasljlasfjlasjfakdlsfjasklfajsklfjaskljlf", 123},
{"ldfjaslk}sfjalskdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj", 1},
{"ldafjaslk}sfjalskdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj", 1},
{"ldjaksdfjfjaslk}sfjalskdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj", 1},
{"ldfjaslk}sfdasfdsfjalskdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj", 1},
{"ldfjaslk}sfjalsksfdasdfdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj", 1},
{"ldfjaslk}sfjalskdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj", 1},
};
std::vector<std::pair<std::string_view, int>> vec;
for (auto& [s, i] : m) {
vec.push_back(std::make_pair(s, i));
std::cout << vec.back().first << std::endl;
}
}
基本上,矢量是使用地图元素创建的。问题是它在插入向量时将字符串转换为 string_view 。我认为这没问题,因为我们使用 const 字符串引用来构造 string_view,并且该字符串将在向量的整个生命周期中可用。
但是当我检查输出时,它显示了看似损坏的数据。
�/�U.�Usfdasdfdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj
�/�U.�Usfjalskdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj
@/�U.�Ukdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj
�/�U.�Usfjalskdfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj
@/�U.�Udfjlkdasjfaslkfjaskdljflaskdfjdaslkfjasdlkfjasdlj
.�Usljlasfjlasjfakdlsfjasklfajsklfjaskljlf
asdf
我猜向量中的 string_view 不再指向正确的元素。但是为什么会这样呢?我假设 unordered_map 在迭代时是不可变的,因此关键元素的地址不会改变。
【问题讨论】:
-
不会
std::make_pair复制字符串,然后 vec 存储对副本的引用吗? -
啊。因此,当我将其修复为
vec.push_back(std::make_pair(std::string_view(s), i));时,它修复了它。但我想知道这怎么会不是默认行为? -
使用
emplace_back和不使用make_pair时效果更好:Live Demo on coliru ;-)
标签: c++