c++ - 如何从 STL 容器中获取只能 move 的类型?

标签 c++ c++11 memory containers move

让我们考虑一个 std::unordered_setstd::unique_ptr<T>举个例子。我可以将集合中的一个元素移到别处吗?

#include <unordered_set>
#include <iostream>
#include <memory>
#include <vector>

int main()
{
    std::unordered_set<std::unique_ptr<int>> mySet;

    mySet.insert(std::make_unique<int>(1));
    mySet.insert(std::make_unique<int>(2));
    mySet.insert(std::make_unique<int>(3));

    std::vector<std::unique_ptr<int>> myVector;

    for (auto&& element : mySet)
    {
        std::cout << *element << std::endl;
        //myVector.push_back(element); won't compile as you can only get a const ref to the key
    }
}

我有一个非常实用的代码示例,我想在其中执行此操作,但被简化为使用 std::shared_ptr .你知道另一个(更好的?)替代品吗?

最佳答案

在 C++03、C++11 和 C++14 中,不直接。您必须将类型更改为:

template <class T>
struct handle {
    mutable std::unique_ptr<T> owning_ptr;
    T* observing_ptr; // enforce that observing_ptr == owning_ptr.get() on construction

    // define operator<, hash, etc. in terms of the observing ptr
};

有了这个,你可以写:

std::unordered_set<handle<int>> mySet;
// initialize as appropriate

for (auto& elem : mySet) {
    myVector.push_back(std::move(elem.owning_ptr));        
}
mySet.clear();

这仍然是定义明确的行为,因为我们没有弄乱任何容器内部 - 观察指针在 clear() 结束之前仍然有效,只是现在 myVector 拥有它。


在C++17中,我们可以在extract()的帮助下直接更简单地做到这一点:

for (auto it = mySet.begin(); it != mySet.end();  
{
    std::cout << **it << std::endl;
    myVector.push_back(std::move(
        mySet.extract(it++).value()));
}

关于c++ - 如何从 STL 容器中获取只能 move 的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39810367/

相关文章:

c++ - 在 C++ 中为派生类定义问题

c++ - 如何在 c 中使用 qsort 比较 C++ 字符串?

c++ - 用于收集可调用对象的 std::function 的替代方法

c++ - 错误生成组合问题的非递归方法

c++ - 使用 new 动态分配字符是否需要编译器将它们初始化为零

c++ - 有没有办法恢复嵌入在 boost mpl 引用中的原始模板模板类?

c++ - 在 700,000 个 vector 元素处突然出现内存峰值

C++ 在内存中按字节移动

Objective-C [在 OS X Leopard 上] 垃圾回收,无问题

c++ - 如何确定我们是否在主线程中运行?