std::set 唯一 ptr 范围插入

Posted

技术标签:

【中文标题】std::set 唯一 ptr 范围插入【英文标题】:std::set of unique ptr range insert 【发布时间】:2017-09-27 23:05:43 【问题描述】:

我有 2 个数据结构,其中包含一组 unique_ptr 像这样

std::vector<std::unique_ptr<Entity>> tmpEnts;
std::set<std::unique_ptr<Entity>> tmpSet;

我正在尝试执行如下所示的插入,但在编译时出现错误。我是智能指针的新手。

tmpSet.insert(tmpEnts.begin(), tmpEnts.end());

tmpEnts其实是一个简化,它实际上驻留在std::map&lt;uint, std::vector&lt;std::unique_ptr&lt;Entity&gt;&gt;&gt; entities

编辑

这个错误占用了很多空间,但我认为这里有些东西我还不太明白。

/home/evgen/workspace/test/ecs/src/entity_manager.cpp:41:22:   required from here
/usr/include/c++/7.2.0/ext/new_allocator.h:136:4: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Entity; _Dp = std::default_delete<Entity>]’
   ::new((void *)__p) _Up(std::forward<_Args>(__args)...); 
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/7.2.0/memory:80:0,
                 from /home/evgen/workspace/test/ecs/src/entity.hpp:4,
                 from /home/evgen/workspace/test/ecs/src/entity_manager.cpp:4:
/usr/include/c++/7.2.0/bits/unique_ptr.h:388:7: note: declared here
       unique_ptr(const unique_ptr&) = delete;

【问题讨论】:

疯狂猜测我假设您的编译器尝试使用复制 .insert() 范围,如果在 std::unique_ptr 上执行它是禁止的 是的,我也有类似的想法,我尝试使用 std::move。得到同样的错误。 【参考方案1】:
tmpSet.insert(tmpEnts.begin(), tmpEnts.end());

正在尝试将元素从 vector 复制到 set。编译失败,因为unique_ptr 不可复制,必须移动。您可以改用move_iterators 来移动元素。

tmpSet.insert(
    std::make_move_iterator(tmpEnts.begin()),
    std::make_move_iterator(tmpEnts.end()));

请注意,在上述调用之后,vector 中的每个 Entity 对象都将被移出。

【讨论】:

是的,我知道 unique_ptr 的独占所有权。我不知道make_move_iterator。多谢! :D 有效 是的。 use of deleted function 'unique_ptr(const std::unique_ptr&amp;)' "你不能复制 unique_ptr" 他不是摔倒了吗?哈哈【参考方案2】:

首先,让我说,如果您打算移动这些指针,unique_ptr 不是首选方式,而是shared_ptr

其次,unique_ptr-s 不能直接插入到 adt 中。他们必须被移动。所以为了让你的代码工作,你必须使用std::move语义:

std::set<std::unique_ptr<int>> tmpSet;

int main(int argc, char ** argv) 
    tmpSet.insert(std::move(std::make_unique<int>(1)));
    tmpSet.insert(std::move(std::make_unique<int>(2)));

或者,当从一个广告移动到另一个广告时:

std::vector<std::unique_ptr<int>> tmpEnts;
std::set<std::unique_ptr<int>> tmpSet;

int main(int argc, char ** argv) 
    tmpEnts.push_back(std::move(std::make_unique<int>(1)));
    tmpEnts.push_back(std::move(std::make_unique<int>(2)));

    auto from = std::make_move_iterator(tmpEnts.begin());
    auto to = std::make_move_iterator(tmpEnts.end());
    tmpSet.insert(from, to);

【讨论】:

当我使用向量的迭代器将数据复制到集合时,我明白了我所说的那部分,这就是我迷路的地方。 @EvgenyDanilenko,我添加了将数据从向量复制到集合的缺失实现。 是的,我不知道 std::make_move_iterator。我对 c++ 也比较陌生,但对编程并不陌生。通过构建一个简单的 2d 引擎开始学习 c++。目前正在实现我的 ecs 架构。谢谢你的回答:)

以上是关于std::set 唯一 ptr 范围插入的主要内容,如果未能解决你的问题,请参考以下文章

插入 std::set<std::tuple<std::string, ...>> 时重复

std::set 插入器不尊重自定义比较器。 (可能的编译器错误?)

不区分大小写的 std::set 字符串

std::Set

为啥在将唯一指针插入无序映射时 C++ 会给我一个错误?

C++ std::set emplace 返回值 first second