2

我正在尝试将指向堆栈变量的指针传递给仅需要boost::shared_ptr.

根据这个答案,使用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);

谢谢!

4

2 回答 2

3

给定boost::make_shared<T>模板:

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

模板机制可以推断参数的类型arg1。因为它“看到”了参数的类型i(即int)。但是,它不能推断出返回类型T。它不知道您将分配给的类型Tboost::shared_ptr<T>即它无法知道 的类型int_ptr。)

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

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

隐式类型转换不会:

double d = 10.0;
std::shared_ptr<int> int_ptr = my_make_shared(d); // ERROR

希望能帮助到你!

于 2017-03-17T19:05:28.163 回答
0

虽然Guilherme Ferreira的答案详细说明了模板参数推导(并且在这方面是正确的),但我相信这不是您要寻找的答案。

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

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

如果满足此条件,您可以创建shared_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现有对象,你必须直接使用它的构造函数。此外,由于对象的生命周期由堆栈控制,因此您必须禁止shared_ptr销毁该对象。这可以通过在shared_ptr构造时指定无操作删除器来完成。

void foo()
{
    int n = 10;
    boost::shared_ptr< int > pn(&n, boost::null_deleter());

    assert(*pn == 10); // succeeds
    assert(pn.get() == &n); // succeeds

    bar(pn);
}

但是请注意,此代码仍为引用计数器的shared_ptr使用分配堆内存,因此您不会赢得任何性能。

于 2017-03-20T13:18:28.900 回答