不使用模板参数来提升make_shared

时间:2017-03-17 17:59:01

标签: c++ boost make-shared

我正在尝试将指向堆栈变量的指针传递给只需要boost::shared_ptr的函数(我无法控制)。

根据this answer,使用boost::make_shared是可行的方法。为了测试这个功能,我写了这个:

#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

int main(int argc, char const *argv[])
{
    int i = 10;
    boost::shared_ptr<int> int_ptr = boost::make_shared(i); // doesn't work
    some_function(int_ptr); // this function takes only shared_ptr
    return 0;
}

但它会引发以下错误:

error: no matching function for call to ‘make_shared(int&)’
boost::shared_ptr<int> int_ptr = boost::make_shared(i);
                                                     ^

如果我像这样添加模板参数它可以工作但是这是什么原因?

boost::shared_ptr<int> int_ptr = boost::make_shared<int>(i);

谢谢!

2 个答案:

答案 0 :(得分:3)

鉴于boost::make_shared<T>模板:

namespace boost {
    template<typename T, typename Arg1>
      shared_ptr<T> make_shared( Arg1 const & arg1 );
}

模板机制可以推导出参数arg1的类型。因为它&#34;看到&#34;参数i的类型(int)。但是,它无法推断出返回类型T。它不知道您将分配给T的{​​{1}}类型(即,它无法知道boost::shared_ptr<T>的类型。)

int_ptr对参数(boost::shared_ptr<T>)使用不同的类型并返回(Arg1)以允许您从不同于指针类型的参数构建共享指针。例如,Tdouble

int

如果要构建类型与参数相同的共享指针,可以编写包装器:

double d = 10.0;
std::shared_ptr<int> int_ptr = std::make_shared<int>(d);

但请记住,虽然这有效:

template<typename T>
boost::shared_ptr<T> my_make_shared(T const & arg) {
    return boost::make_shared<T>(arg);
}

隐式类型转换不会:

int i = 10.0;
std::shared_ptr<int> int_ptr = my_make_shared(i); // OK

希望它有所帮助!

答案 1 :(得分:0)

虽然 Guilherme Ferreira 的回答详细阐述了模板参数演绎(在这方面是正确的),但我相信这不是您正在寻找的答案。

  

我正在尝试将指向堆栈变量的指针传递给只接受boost :: shared_ptr的函数(我无法控制)。

PDO_MySQL表示对指向对象的共享所有权。如果您尝试调用的函数将指针保存在其某些数据结构中(如容器),然后返回,则只要堆栈上的值被销毁,指针就会变为悬空,尽管{{1仍然有一个参考。为了做你想做的事,你必须绝对确定该函数不会将指针保存在任何地方,并且只能在这一次调用期间使用它。

如果满足此条件,您可以创建指向堆栈上的值的shared_ptr,但不能使用shared_ptrshared_ptr 在堆上分配一个新对象以及它的引用计数器,并使用传递给函数调用的参数对其进行初始化。返回的make_shared指向该新对象,而不指向堆栈中的对象。

make_shared

这意味着对shared_ptr的修改void foo() { int n = 10; boost::shared_ptr< int > pn = boost::make_shared< int >(n); assert(*pn == 10); // succeeds assert(pn.get() == &n); // fails bar(pn); } 不会反映在bar上。

要为现有对象创建int,必须直接使用其构造函数。此外,由于对象的生命周期由堆栈控制,因此必须禁止n销毁对象。这可以通过在shared_ptr构造上指定no-op删除器来完成。

shared_ptr

但请注意,此代码仍为参考计数器shared_ptr使用的堆内存分配,因此您无法获得任何性能。

相关问题