boost make_shared 没有模板参数
boost make_shared without template argument
我正在尝试将一个指向堆栈变量的指针传递给一个只接受 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);
谢谢!
给定 boost::make_shared<T>
模板:
namespace boost {
template<typename T, typename Arg1>
shared_ptr<T> make_shared( Arg1 const & arg1 );
}
模板机制可以推导出参数的类型arg1
。因为它 "sees" 参数的类型 i
(即 int
)。但是,它不能推导出 return 类型 T
。它不知道您将分配给 boost::shared_ptr<T>
的类型 T
(即它无法知道 int_ptr
的类型)
boost::shared_ptr<T>
使用不同类型的参数 (Arg1
) 和 return (T
) 以允许您从不同于指针类型的参数构建共享指针.例如,double
到 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
隐式类型转换不会:
double d = 10.0;
std::shared_ptr<int> int_ptr = my_make_shared(d); // ERROR
希望对您有所帮助!
虽然 Guilherme Ferreira 的回答详细阐述了模板参数推导(并且在这方面是正确的),但我相信这不是您要找的答案。
I'm trying to pass a pointer to a stack variable to a function (I don't control) that only takes a boost::shared_ptr.
shared_ptr
表示指向对象的共享所有权。如果你试图调用的函数将指针保存在它的某些数据结构中,比如容器,然后 returns,那么一旦堆栈上的值被销毁,指针就会变成悬垂状态,尽管事实上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
使用分配堆内存,因此您不会赢得任何性能。
我正在尝试将一个指向堆栈变量的指针传递给一个只接受 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);
谢谢!
给定 boost::make_shared<T>
模板:
namespace boost {
template<typename T, typename Arg1>
shared_ptr<T> make_shared( Arg1 const & arg1 );
}
模板机制可以推导出参数的类型arg1
。因为它 "sees" 参数的类型 i
(即 int
)。但是,它不能推导出 return 类型 T
。它不知道您将分配给 boost::shared_ptr<T>
的类型 T
(即它无法知道 int_ptr
的类型)
boost::shared_ptr<T>
使用不同类型的参数 (Arg1
) 和 return (T
) 以允许您从不同于指针类型的参数构建共享指针.例如,double
到 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
隐式类型转换不会:
double d = 10.0;
std::shared_ptr<int> int_ptr = my_make_shared(d); // ERROR
希望对您有所帮助!
虽然 Guilherme Ferreira 的回答详细阐述了模板参数推导(并且在这方面是正确的),但我相信这不是您要找的答案。
I'm trying to pass a pointer to a stack variable to a function (I don't control) that only takes a boost::shared_ptr.
shared_ptr
表示指向对象的共享所有权。如果你试图调用的函数将指针保存在它的某些数据结构中,比如容器,然后 returns,那么一旦堆栈上的值被销毁,指针就会变成悬垂状态,尽管事实上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
使用分配堆内存,因此您不会赢得任何性能。