c++ - 来自抽象类的 unique_ptr 的 shared_ptr

标签 c++ c++11 abstract unique-ptr make-shared

我正在尝试遵循 Herb Sutter 的 C++ 指南,在这种情况下,我更喜欢 unique_ptr 而不是原始指针和 shared_ptr。支持 std::unique_ptr 的论点之一是在某些时候需要时可以转换为 shared_ptr

在我的例子中,我有一个 vectorunique_ptr 我需要传递给一个方法,该方法采用 shared_ptr 的 vector 。我希望能够写出类似这样的东西:

for (auto &uniquePtr : vectorUnique)
    vectorShared.push_back(make_shared<Abstract>(move(uniquePtr));

这为我的 Xcode 7.1 配置了 C++11 的工具链带来了以下错误:

error: field type 'Abstract' is an abstract class.

当我使用 make_shared 时,STL 似乎试图保存类型为 Abstract 的具体实例。在许多情况下,这似乎会使 Sutter 先生的建议行不通,所以我确定我一定做错了什么!我求助于写作:

for (auto &uniquePtr : vectorUnique) {
    auto ptr = uniquePtr.get();
    auto shared = shared_ptr<Abstract>(ptr);
    vectorShared.push_back(shared);
    uniquePtr.release();
}

有更好的方法吗?

最佳答案

make_shared使用给定的参数构造一个新对象并返回一个 shared_ptr给它。所以编译器需要一个构造函数 Abstract(std::unique_ptr<Abstract>) ,这可能不是您拥有的。

你想要的是shared_ptr的构造函数这需要 unique_ptr参数:

    vectorShared.push_back(shared_ptr<Abstract>(move(uniquePtr)));

而且,因为它不是 explicit , 然后

    vectorShared.emplace_back(move(uniquePtr));

将正常工作(根据 Richard Hodges 的建议,我使用 emplace_back 来避免冗余复制)。甚至还有一个标准算法,因此您不需要 for循环:

    std::move(vectorUnique.begin(), vectorUnique.end(),
              std::back_inserter(vectorShared));

如果你经常需要这个,你可以定义一个函数:

#include <vector>
#include <memory>
#include <algorithm>

template<typename T>
std::vector<std::shared_ptr<T>>
        convert_to_shared(std::vector<std::unique_ptr<T>>&& vu)
{
    using std::begin;
    using std::end;
    std::vector<std::shared_ptr<T>> vs;
    vs.reserve(vu.size());
    std::move(begin(vu), end(vu), std::back_inserter(vs));
    return vs;
}


// Example of use
class Abstract {};
int main()
{
    std::vector<std::unique_ptr<Abstract>> vectorUnique;
    std::vector<std::shared_ptr<Abstract>> vectorShared
        = convert_to_shared(std::move(vectorUnique));
}

抱歉这个糟糕的名字(我愿意接受建议)。如果您省略对 reserve() 的调用,您可以将其推广到更多容器。

关于c++ - 来自抽象类的 unique_ptr 的 shared_ptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34163186/

相关文章:

c++ - 动态覆盖

c++ - Visual Studio 正则表达式替换

java - 在 C++ 中正确表示 Java 的 ArrayList<Object>

c++11 decltype 返回引用类型

C#抽象类有另一个抽象类对象

c# - 为什么 C# 支持抽象成员的抽象覆盖?

c++ - 将数据从 vector 写入文件。 C++

没有宏的 C++ 配置方法

c++ - 删除构造函数后的初始化

c++ - 无法启动抽象类,因为成员是抽象的