关于shared_ptr - C ++用法的问题

时间:2010-01-27 05:46:09

标签: c++ smart-pointers shared-ptr

关于使用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;
}

任何帮助都会很棒。

5 个答案:

答案 0 :(得分:8)

大多数问题已经得到解答,但我不同意shared_ptr副本很便宜。

副本与传递引用具有不同的语义。它将修改引用计数,这将在最佳情况下触发原子增量,在最坏情况下触发锁定。 您必须确定所需的语义,然后您将知道是通过引用还是通过值传递。

从性能的角度来看,使用boost指针容器而不是shared_ptr的容器通常更好。

答案 1 :(得分:4)

  1. 复制很便宜,指针不占用太多空间。它的重点是使其小到允许按值使用容器(例如std::vector< shared_ptr<Foo> >)。

  2. make_shared获取可变数量的参数,并且是自己构建它的首选机制(就像make_pair)。优点是可读性,尤其是涉及传递临时和/或命名空间时:

  3. boost::const_ptr_cast已经建议

  4. 智能指针有重载运算符,可以直接用于评估为bool的表达式中。不要使用get。为了任何东西。不要将p.get与任何事物进行比较,而是比较空指针实例(my_ptr != boost::shared_ptr< MyClass >()

  5. 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)

  1. 是的,副本绝对便宜。除了保持指针之外,还有(通常)shared_ptr类的另一个数据成员 - 使用计数。
  2. 无法回答这个问题,我通常在引入make_shared之前使用boost版本(1.40?)
  3. 使用boost :: const_pointer_cast
  4. shared_ptr有operator == /!=已定义。在上面的示例中:if(f)

答案 3 :(得分:3)

  1. 现在复制shared_ptr会使堆栈副本中的32个字节和额外的refcount递增/递减成本。决定它是否对你便宜,但我认为没有理由不传递const引用,特别是你已经为ptr设置了一个typedef: void f(const foo_ptr &myfoo) 特别是考虑到在C ++中传递的标准no-write-permissions参数是const引用。

  2. 我更希望没有接受未共享指针的函数。这与Java和C#中的参数传递语义类似(尽管不完全相同)。为什么每次都决定如何传递一个对象,而不是采用一种标准的方式来做?

  3. 使用if(p)就像常规指针一样。布尔转换语义非常简洁。

答案 4 :(得分:2)

  1. 存在shared_ptr的一个基本原因是复制起来相对便宜。
  2. 有些参数的make_shared版本(如果您的编译器支持可变参数模板,那么它将采用变量参数列表。)
  3. 听起来你在寻找const_ptr_cast?
  4. 要返回空指针,可以将'0'传递给share_ptr ctor。要检查空指针,可以将p.get()与0进行比较。