gpt4 book ai didi

c++ - 将对象从一个 unordered_map move 到另一个容器

转载 作者:IT老高 更新时间:2023-10-28 23:20:57 27 4
gpt4 key购买 nike

我的问题是安全问题。我搜索了 cplusplus.com 和 cppreference.com,它们在 std::move 期间似乎缺乏迭代器安全性。具体来说:使用对象已被 move 的迭代器调用 std::unordered_map::erase(iterator) 是否安全?示例代码:

#include <unordered_map>
#include <string>
#include <vector>
#include <iostream>
#include <memory>

class A {
public:
A() : name("default ctored"), value(-1) {}
A(const std::string& name, int value) : name(name), value(value) { }
std::string name;
int value;
};
typedef std::shared_ptr<const A> ConstAPtr;

int main(int argc, char **argv) {
// containers keyed by shared_ptr are keyed by the raw pointer address
std::unordered_map<ConstAPtr, int> valued_objects;

for ( int i = 0; i < 10; ++i ) {
// creates 5 objects named "name 0", and 5 named "name 1"
std::string name("name ");
name += std::to_string(i % 2);

valued_objects[std::make_shared<A>(std::move(name), i)] = i * 5;
}

// Later somewhere else we need to transform the map to be keyed differently
// while retaining the values for each object

typedef std::pair<ConstAPtr, int> ObjValue;

std::unordered_map<std::string, std::vector<ObjValue> > named_objects;

std::cout << "moving..." << std::endl;

// No increment since we're using .erase() and don't want to skip objects.
for ( auto it = valued_objects.begin(); it != valued_objects.end(); ) {
std::cout << it->first->name << "\t" << it->first.value << "\t" << it->second << std::endl;

// Get named_vec.
std::vector<ObjValue>& v = named_objects[it->first->name];
// move object :: IS THIS SAFE??
v.push_back(std::move(*it));

// And then... is this also safe???
it = valued_objects.erase(it);
}

std::cout << "checking... " << named_objects.size() << std::endl;
for ( auto it = named_objects.begin(); it != named_objects.end(); ++it ) {
std::cout << it->first << " (" << it->second.size() << ")" << std::endl;
for ( auto pair : it->second ) {
std::cout << "\t" << pair.first->name << "\t" << pair.first->value << "\t" << pair.second << std::endl;
}
}

std::cout << "double check... " << valued_objects.size() << std::endl;
for ( auto it : valued_objects ) {
std::cout << it.first->name << " (" << it.second << ")" << std::endl;
}

return 0;
}

我问的原因是让我感到震惊的是,从 unordered_map 的迭代器中 move 该对可能(?)因此 *re* move 迭代器的存储键值,从而使其哈希无效;因此,之后对其进行的任何操作都可能导致未定义的行为。除非不是这样?

我确实认为值得注意的是,上述内容似乎在 GCC 4.8.2 中成功地按预期工作,所以我想看看我是否错过了支持或明确不支持该行为的文档。

最佳答案

// move object :: IS THIS SAFE??
v.push_back(std::move(*it));

是的,它是安全的,因为这实际上并没有修改 key 。它不能,因为关键是 const。 *it的类型是 std::pair<const ConstAPtr, int> .当它被 move 时,第一个成员(const ConstAPtr)实际上并没有被 move 。它通过 std::move 转换为 r 值, 并变为 const ConstAPtr&& .但这与 move 构造函数不匹配,它需要一个非常量 ConstAPtr&& .所以调用了复制构造函数。

关于c++ - 将对象从一个 unordered_map move 到另一个容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24126635/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com