C++ 将关键帧移出std::map<&燃气轮机&&;
我想让C++ 将关键帧移出std::map<&燃气轮机&&;,c++,stdmap,C++,Stdmap,我想让getKeys()函数从map中获取不可复制的键: class MyObj { // ... complex, abstract class... }; struct Comparator { bool operator()(std::unique_ptr<MyObj> const &a, std::unique_ptr<MyObj> const &b); }; std::vector<std::unique_ptr<MyObj&
getKeys()
函数从map
中获取不可复制的键:
class MyObj {
// ... complex, abstract class...
};
struct Comparator { bool operator()(std::unique_ptr<MyObj> const &a, std::unique_ptr<MyObj> const &b); };
std::vector<std::unique_ptr<MyObj>> getKeys(std::map<std::unique_ptr<MyObj>, int, Comparator> &&map) {
std::vector<std::unique_ptr<MyObj>> res;
for (auto &it : map) {
res.push_back(std::move(it.first));
}
return res;
}
我想避免克隆MyObj
我知道为什么不能修改
std::map
容器的键,但是对于在键修改后立即销毁的映射,仍然不允许修改吗?是的,仍然不允许。如果您只是想在事后销毁映射,那么对密钥的非常量访问可能是安全的,但是标准并不能保证它是安全的,std::map
接口也没有提供任何适用于右值引用的规则的放松
然而,自C++17以来,std::map
所拥有的是extract()
,它将一个键值对从映射中完全剥离出来,并将其作为“节点句柄”返回。此节点句柄提供对密钥的非常量访问。因此,如果要将指针移出该节点句柄,则最终将对空指针进行销毁
例如:
#包括
#包括
#包括
#包括
模板
标准::向量提取键(标准::映射和映射)
{
std::向量res;
而(!map.empty())
{
自动句柄=map.extract(map.begin());
res.emplace_back(std::move(handle.key());
}
返回std::移动(res);
}
int main()
{
地图;
映射位置(std::make_pair(std::make_unique(3,4));
自动向量=提取键(标准::移动(映射));
返回*vec[0];
}
注意:在我们的环境中,我不允许使用C++17函数std::map::extract()
羞耻感-它的出现是为了解决这个问题
使用const\u cast
是否可以,因为地图无论如何都会被破坏
res.push_back(std::move(const_cast<std::unique_ptr<MyObj> &>(it.first)));
没有
我想避免克隆MyObj
对不起;您至少需要克隆密钥
我知道为什么不能修改std::map
容器的键,但是对于在键修改后立即销毁的映射,仍然不允许修改吗
对
地图的内部机制无法知道它的命运在等待着我。答案让我相信我应该避免使用const_-cast-ing。经过一些分析,我意识到我的映射在代码中的使用是非常孤立的,因此我可以进行一个小的重构来避免常量问题
结果如下:
class MyObj {
// ... complex, abstract class...
};
struct Comparator { bool operator()(MyObj const *a, MyObj const *b); };
// key is a pointer only, value holds the key object and the effective "value"
struct KeyAndVal { std::unique_ptr<MyObj> key; int val; };
using MyMap = std::map<MyObj *, KeyAndVal, Comparator>;
// Example how emplace should be done
auto myEmplace(MyMap &map, std::unique_ptr<MyObj> key, int val) {
auto *keyRef = key.get(); // to avoid .get() and move in one expr below
return map.emplace(keyRef, KeyAndVal{ std::move(key), val });
}
std::vector<std::unique_ptr<MyObj>> getKeys(MyMap map) {
std::vector<std::unique_ptr<MyObj>> res;
for (auto &it : map) {
res.push_back(std::move(it.second.key));
}
// here 'map' is destroyed but key references are still valid
// (moved into return value).
return res;
}
类MyObj{
//…复杂的抽象类。。。
};
结构比较器{bool操作符()(MyObj常量*a,MyObj常量*b);};
//key仅为指针,value保存key对象和有效的“value”
结构KeyAndVal{std::uniqueptrkey;int val;};
使用MyMap=std::map;
//应如何安置的示例
自动myEmplace(MyMap&map,std::unique_ptr key,int val){
auto*keyRef=key.get();//避免.get()并在下面的一个表达式中移动
返回map.emplace(keyRef,KeyAndVal{std::move(key),val});
}
std::vector getkey(MyMap){
std::向量res;
用于(自动&it:map){
res.push_back(std::move(it.second.key));
}
//此处“地图”已销毁,但关键引用仍然有效
//(移动到返回值中)。
返回res;
}
你能从std::unique_ptr
切换到std::shared_ptr
吗?请看下面我如何解决这个问题的答案。删除一个又一个键可能会导致很多树重新平衡。不过,这似乎是唯一完全合法的再次取出钥匙的方法…@阿肯卡瓜同意。我想在这种情况下,我可能会结合使用const\u cast
,并希望达到最好的效果:-你注意到OP不允许使用C++17吗?在我看来,他/她似乎知道std::map::extract
,只是不能使用它。你答案的第二部分对我来说似乎完全多余,包括整个代码。(还要注意,您的extractKeys
函数将只接受带有默认comparator和allocator模板参数的map
s,这不是OP的情况。)不,我错过了OP消息的那一部分(但请记住,答案应该是广泛适用的,而不仅仅适用于原始提问者)。该代码旨在说明该技术,而不是未经修改就使用。它们应该适用于const_cast
::的问题思路。