4

在一些旧代码上使用 C++10 的新功能时,我最终遇到了无法调用make_shared需要 12 个参数的问题。我记得微软的 STL 谈到他们如何使用仿真,make_shared并且最多 10 个。make_shared显然,仅仅为此重构代码是不可能的,所以基本上我的问题是 - 有没有办法在 VS 2010中获得超过 10 个参数。

4

2 回答 2

11
make_shared<foobar>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);

可以替换为

shared_ptr<foobar>(new foobar(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12));

在 C++11 中,std::make_shared 实际上是对使用第二种方法创建对象的性能优化,因为它只执行一次内存分配而不是两次,但是一旦超过 10 个变量,你就没有太多选择了关于使用哪个。

于 2013-01-18T00:12:51.450 回答
1

如果你真的想利用make_shared它的效率优势,那么你仍然可以这样做:

#include <tuple>
#include <memory>
#include <redi/index_tuple.h>

template<typename X, typename... Args>
  std::shared_ptr<X>
  make_shared_TO_THE_MAX(Args&&... args)
  {
    struct Wrapper
    {
      X x;

      template<typename... T>
        Wrapper(std::tuple<T...> targs) : Wrapper(targs, to_index_tuple<T...>{}) { }

      template<typename T, unsigned... I>
        Wrapper(T targs, index_tuple<I...>) : x(std::get<I>(targs)) { }
    };

    auto wrapped = std::make_shared<Wrapper>(std::forward_as_tuple(std::forward<Args>(args)...));
    return std::shared_ptr<X>(wrapped, &wrapped->x);
  }

这将构造函数参数捆绑到一个引用元组中并将其传递给make_shared,因此make_shared不能处理 10 个参数并不重要,因为它只有一个。而不是make_shared<X>它使用make_shared<Wrapper>which 将为 a 分配空间Wrapper(它的大小和布局与其类型的成员相同X)并使用参数元组构造它。构造函数委托给另一个构造函数,该Wrapper构造函数扩展元组以传递给X构造函数。

最后,它使用shared_ptr别名构造函数返回shared_ptr<X>与 共享所有权shared_ptr<Wrapper>但存储X对象地址的 a。

<redi/index_tuple.h>我自己的标题,但我正在尝试为 C++14 获得类似的标准化。

这也可以在没有可变参数模板的情况下完成,但工作量更大。这是两个参数,十二个再加十个!

#include <tuple>
#include <memory>

template<typename X, typename Arg0, typename Arg1>
  std::shared_ptr<X>
  make_shared_TO_THE_MAX(Arg0&& arg0, Arg1&& arg1)
  {
    struct Wrapper
    {
      X x;

      template<typename T0, typename T1>
        Wrapper(std::tuple<T0, T1> targs)
        : x(std::get<0>(targs), std::get<1>(targs)) { }
    };

    auto wrapped = std::make_shared<Wrapper>(std::forward_as_tuple(std::forward<Arg0>(arg0), std::forward<Arg1>(arg1)));
    return std::shared_ptr<X>(wrapped, &wrapped->x);
  }
于 2013-01-20T12:21:49.197 回答