【问题标题】:How do I understand how std::make_shared works?我如何理解 std::make_shared 的工作原理?
【发布时间】:2021-08-15 15:46:35
【问题描述】:

我遇到了一条优雅的线,将二进制文件读入这样的向量(有效):

        std::ifstream ifs("myfile.bin", std::ios::binary);
        std::vector<char> buffer(std::istreambuf_iterator<char>(ifs), {});

相反,因为我希望我的向量成为我写的共享指针:

        std::ifstream ifs("myfile.bin", std::ios::binary);
        auto sp = std::make_shared<std::vector<char>>(std::istreambuf_iterator<char>(ifs), {});

即只需将向量构造函数参数传递给 make_shared (就像我通常创建任何对象的任何共享指针一样)。 但我得到:错误:没有匹配函数调用'make_shared'?

详细输出:

/usr/include/c++/11.1.0/bits/shared_ptr.h|873 col 5|注意:候选模板被忽略:替换失败 [with _Tp = std::vector]:推导出模板的不完整包 <:istreambuf_iterator std::char_traits>, (no value)>参数“_Args” || make_shared(_Args&&... __args)

【问题讨论】:

  • 你忘记#include &lt;memory&gt;了吗?
  • 我的第一个想法,但我没有
  • 因为这是一个仅将参数转发给构造函数的可变参数函数,因此无法在此上下文中推断出您传递的 {} 的含义,因为没有声明特定的参数类型位置。因此,您需要传递特定类型的对象,在这种情况下,我猜是相关的std::istreambuf_iterator&lt;char&gt;{} - 而不是花括号初始化列表。错误可能会说,如果你引用它...
  • @Jörgen {} 在函数调用中表示“根据其类型默认初始化此参数”。如果函数是为该参数模板化的,编译器如何知道它是什么类型?并且std::make_shared&lt;&gt;() 必须被模板化,因为它只是将参数转发给包含类型的构造函数,但要做到这一点,它必须确切地知道它们是什么类型。带括号的初始化列表没有类型(在这种情况下,至少不是空的;在其他地方,例如 {42} 会推断为 std::initializer_list&lt;int&gt;)。
  • @Jörgen - {} 仅在目标类型已知时才有意义。它本身不是类型系统的一部分(哎呀,它甚至不是表达式)。当{} 的目标类型未知时(例如尝试推断其类型开始时),它是没有意义的。

标签: c++ shared


【解决方案1】:

这将起作用:

std::ifstream ifs("myfile.bin", std::ios::binary);
auto sp = std::make_shared<std::vector<char>>(std::istreambuf_iterator<char>(ifs),
    std::istreambuf_iterator<char>{});

这是因为您使用的是这个可变参数模板:

template<class T, class... Args>
shared_ptr<T> make_shared( Args&&... args );

如果不是手动实例化,每个单独的参数类型都必须是可推导的。 '{}' 不允许参数推导,因此编译器错误。遗憾的是,您还可以显式实例化模板:

auto sp = std::make_shared<std::vector<char>, std::istreambuf_iterator<char>,
    std::istreambuf_iterator<char>>({ifs}, {});

在这两种情况下,迭代器的类型别名可能会提高可读性(using InputIt = std::istreambuf_iterator&lt;char&gt;; 或类似的东西)。

【讨论】:

    猜你喜欢
    • 2020-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-10
    • 2014-04-08
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多