关于使用shared_ptr
的最佳做法,我几乎没有问题。
问题1
复制shared_ptr
便宜吗?或者我是否需要将其作为参考传递给我自己的帮助函数并返回值?像,
void init_fields(boost::shared_ptr<foo>& /*p_foo*/);
void init_other_fields(boost::shared_ptr<foo>& /*p_foo*/);
boost::shared_ptr<foo> create_foo()
{
boost::shared_ptr<foo> p_foo(new foo);
init_fields(p_foo);
init_other_fields(p_foo);
}
问题2
我应该使用boost::make_shared
来构建shared_ptr
吗?如果是,它提供了哪些优势?当make_shared
没有无参数构造函数时,我们如何使用T
?
问题3
如何使用const foo*
?我找到了两种方法。
void take_const_foo(const foo* pfoo)
{
}
int main()
{
boost::shared_ptr<foo> pfoo(new foo);
take_const_foo(pfoo.get());
return 0;
}
OR
typedef boost::shared_ptr<foo> p_foo;
typedef const boost::shared_ptr<const foo> const_p_foo;
void take_const_foo(const_p_foo pfoo)
{
}
int main()
{
boost::shared_ptr<foo> pfoo(new foo);
take_const_foo(pfoo);
return 0;
}
问题4
如何在NULL
对象上返回并检查shared_ptr
?它是什么样的,
boost::shared_ptr<foo> get_foo()
{
boost::shared_ptr<foo> null_foo;
return null_foo;
}
int main()
{
boost::shared_ptr<foo> f = get_foo();
if(f == NULL)
{
/* .. */
}
return 0;
}
任何帮助都会很棒。
答案 0 :(得分:8)
大多数问题已经得到解答,但我不同意shared_ptr副本很便宜。
副本与传递引用具有不同的语义。它将修改引用计数,这将在最佳情况下触发原子增量,在最坏情况下触发锁定。 您必须确定所需的语义,然后您将知道是通过引用还是通过值传递。
从性能的角度来看,使用boost指针容器而不是shared_ptr的容器通常更好。
答案 1 :(得分:4)
复制很便宜,指针不占用太多空间。它的重点是使其小到允许按值使用容器(例如std::vector< shared_ptr<Foo> >
)。
make_shared
获取可变数量的参数,并且是自己构建它的首选机制(就像make_pair
)。优点是可读性,尤其是涉及传递临时和/或命名空间时:
智能指针有重载运算符,可以直接用于评估为bool的表达式中。不要使用get
。为了任何东西。不要将p.get
与任何事物进行比较,而是比较空指针实例(my_ptr != boost::shared_ptr< MyClass >()
)
AD.2
func_shared( boost::shared_ptr<my_tools::MyLongNamedClass>(
new my_tools::MyLongNamedClass( param1, param2 ) );
与
func_shared( boost::make_shared<my_tools::MyLongNamedClass>( param1, param2 ));
答案 2 :(得分:3)
答案 3 :(得分:3)
现在复制shared_ptr会使堆栈副本中的32个字节和额外的refcount递增/递减成本。决定它是否对你便宜,但我认为没有理由不传递const引用,特别是你已经为ptr设置了一个typedef:
void f(const foo_ptr &myfoo)
特别是考虑到在C ++中传递的标准no-write-permissions参数是const引用。
我更希望没有接受未共享指针的函数。这与Java和C#中的参数传递语义类似(尽管不完全相同)。为什么每次都决定如何传递一个对象,而不是采用一种标准的方式来做?
使用if(p)
就像常规指针一样。布尔转换语义非常简洁。
答案 4 :(得分:2)