【问题标题】:Initializing std::shared_ptr with std::make_shared having an std::array as argument使用 std::make_shared 以 std::array 作为参数初始化 std::shared_ptr
【发布时间】:2020-01-27 23:59:09
【问题描述】:

我不明白为什么这样可以正常工作:

std::array<double, 2> someArray = {0,1};
std::shared_ptr<MyClass> myobj = std::make_shared<MyClass>(someArray);

但这不起作用:

std::shared_ptr<MyClass> myobj = std::make_shared<MyClass>({0,1});

编译器说:

too many arguments to function ‘std::shared_ptr< _Tp> std::make_shared(_Args&& ...)
...
candidate expects 1 argument, 0 provided

问题:有人能解释一下为什么会发生这种情况吗?是否有任何方法可以在不定义额外变量的情况下修复第二种方法?


编辑: MyClass 示例:

#include <memory> //For std::shared_ptr
#include <array>
#include <iostream>

class MyClass{
  public:
    MyClass(std::array<double, 2> ){
      std::cout << "hi" << std::endl;
    };
};

【问题讨论】:

  • 什么是 MyClass?
  • ...它的构造函数是什么样的?

标签: c++ c++11 std shared-ptr


【解决方案1】:

花括号初始化器 {} 永远不能被推导出为类型(在模板上下文中)。一个特例是auto,它被推导出为std::initializer_list。您总是必须明确定义类型。

auto myobj = std::make_shared<MyClass>(std::array<double, 2>{0, 1});

【讨论】:

  • auto myobj = std::make_shared&lt;MyClass&gt;(std::array{0., 1.}); 也可以。
【解决方案2】:

{0, 0} 的类型取决于上下文。如果{0, 0} 被用于立即构造另一个已知类型的对象,则它表示该对象类型的prvalue

MyClass m({0, 0}); 

这里,{0, 0} 指的是 std::array&lt;double, 2&gt; 类型的纯右值 另一方面,如果对类型没有约束,那么{0, 0} 指的是std::initializer_list&lt;int&gt; 类型的初始化列表:

auto vals = {0, 0};

没有办法从std::initializer_list&lt;int&gt;初始化MyClass,所以make_shared编译失败:

MyClass m(vals); // Fails: can't construct MyClass from initializer list

这如何连接到std::make_shared 因为std::make_shared 是一个模板,所以{0, 0} 不用于构造特定类型。因此,它被视为std::initializer_list

【讨论】:

  • 这是不正确的。 {0, 0} 仅在与 auto 一起使用时是 std::initializer_list&lt;int&gt;。没有就没有类型
  • 传递给模板化函数时不也是一个std::initiaizer_list吗?
  • 没有。为auto 添加了一个特殊规则,因此它可以工作(仍然不确定我是否喜欢)。没有为模板扣除制定规则。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-20
  • 1970-01-01
  • 2014-08-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多