C++ 无序集:随移动一起删除

C++ 无序集:随移动一起删除,c++,c++11,move-semantics,C++,C++11,Move Semantics,在c++11中,std::unordered_set容器提供了一个插入重载和一个新函数emplace,以便可以与非复制可构造键一起使用,例如std::unique_ptr 如果要删除其中一个密钥,会发生什么情况?auto temp=std::move(*某个迭代器)有效吗?有没有什么功能可以让我们同时擦除一个元素并将其移动到一个temp中 编辑:我试着让它简短、甜美、简单,但为了更清楚: 是否有一个迭代器适配器(可能是move_iterator?)可以让我从容器中移动一个元素,并删除该迭代器

在c++11中,std::unordered_set容器提供了一个插入重载和一个新函数emplace,以便可以与非复制可构造键一起使用,例如std::unique_ptr

如果要删除其中一个密钥,会发生什么情况?
auto temp=std::move(*某个迭代器)
有效吗?有没有什么功能可以让我们同时擦除一个元素并将其移动到一个temp中

编辑:我试着让它简短、甜美、简单,但为了更清楚:

  • 是否有一个迭代器适配器(可能是move_iterator?)可以让我从容器中移动一个元素,并删除该迭代器
  • 若否,原因为何?未来的C++不应该包含这种接口吗?

这种情况似乎是不可能的:您不能在删除密钥之前使其无效,也不能在删除密钥之后访问它。

对于
std::unordered\u set
成员
emplace()
使对象不需要移动,或者:您可以
将不可移动的对象放置到容器中


回答这个问题:您不能将
std::move()
元素移出
std::unordered\u集合
,因为元素都是
const
,并且
const
对象不能移动。当您从
std::unordered\u集合
erase()
创建
std::unique\u ptr
时,指向的对象将是
delete
d:在
erase()
删除元素时,没有允许您恢复指针的接口。也没有一个
splice()
成员将元素粘贴到另一个容器中,在该容器中可以忽略它,直到将其清除。

我的解决方案就是将元素放入
std::shared\u ptr
中。通过这种方式,您可以复制它们,然后最终将元素移出
共享\u ptr

在编程方面,这样做的代价是您必须自己定义哈希函数

假设您正在将
std::string
放入集合:

struct MyHasher
{
    size_t operator()(const std::shared_ptr<std::string>& element) const
    {
        return std::hash<std::string>()(*element);
    }
};

现在,您可以随意移动元素。

在C++11中
std::unordered\u容器不存在。@Jeffrey typo,fixed我建议将数据结构从
unordered\u set
切换到
unordered\u map
,这样您就可以在删除之前检索
unique\u ptr
:auto temp=std::move(一些迭代器->秒);
@Casey这只是一个示例(选择为常见)-我想写可以利用非复制可构造对象的通用代码。api似乎是不对称的。是的-这就是我发现自己所处的情况,我想知道是否有办法。似乎在删除元素之前无法使其无效,并且在不删除它的情况下无法删除和元素。我问了这个问题因为这看起来像是第22条军规。除非你有一个标准的摘录说这是不可能的,否则答案不是很有用,对不起。@user3125280:根本没有第22条军规!如果你将一个
std::unique\u ptr
粘贴到
std::无序集
中,你将无法将其从容器中删除,同时保留所有内容也就是说,你想要什么样的标准摘录?
std::unordered_集
只提供对
T const&
的访问权限,没有方法将其恢复为非
const
对象。换句话说,你想做的事情是做不到的。你可以用
std::unordered_映射
做一些类似于你想做的事情,不过:你可以移动值There.There在重新灰化过程中它们是如何移动的?将赋值移动到const?如果我可以擦除它,我应该能够以某种方式从中移动出来。@user3125280:在内部,无序容器保持节点嵌入实际对象(您可以知道,因为重新灰化不会使指向元素的指针无效;只有迭代器无效)。也就是说,在某些指针更新时,实际对象保持不变。这就是我对
splice()
发表评论的原因:内部有某种形式的列表,我可以想象有一种方法可以将节点移动到单独的容器中,但实际上没有。但是如果它被删除(即使是在内部)还有一个可变副本,我无论如何都无法通过任何接口访问它。问题是api支持插入非复制可构造键,但不删除它们。这是移动语义的一个限制。移动与析构函数是分开的,因此不销毁两次就不可能从常量对象移动(在本例中,对同一指针调用delete两次)。通常,api需要访问可变键(坏主意),或者对象需要组合移动/析构函数(坏主意),或者程序员只使用可复制对象(好主意,但单例不应可复制)所以在实践中这不是问题。如果出于某种原因,你对这种事情感兴趣,我在另一个问题@user3125280中问了这个问题,实际上我遇到了这个问题,但是
shared\u ptr
对我的案例来说是一个很好的解决方案。感谢链接:)
std::unordered_set<std::string,MyHasher> the_set;