【问题标题】:Check for null in std::shared_ptr检查 std::shared_ptr 中的空值
【发布时间】:2014-03-06 09:42:31
【问题描述】:

我想知道在使用之前是否需要检查sp 是否为null。 如果我错了,请纠正我,但创建别名不会增加引用计数器,因此通过进入我们正在使用共享指针的方法,我们不知道嵌入指针之前是否已重置..我是否正确假设这个?

Class::MyFunction(std::shared_ptr<foo> &sp)
{    
    ...  
    sp->do_something();  
    ...  
}

【问题讨论】:

  • @Bathsheba:只有他会使用 C++11。不是每个人都是可以控制自己的工具链的业余程序员。
  • @LightnessRacesinOrbit:确实(而且,我承认,在对冲基金工作是一种爱好),但培养必要的个人效率技能以推动公司向前发展很重要。
  • @Bathsheba:我同意:至少在你自己的时间写,是的!

标签: c++ shared-ptr


【解决方案1】:

您必须考虑到std::shared_ptr 总体上仍然是一个指针(封装在类指针中)并且它确实可以be constructed to internally be nullptr。发生这种情况时,表达式如下:

ptr->
*ptr

导致未定义的行为。所以,是的,如果您希望指针也是nullptr,那么您应该使用check for its value

ptr != nullptr

!ptr

(感谢它的operator bool)。

【讨论】:

  • @Jefffrey 除了要避免!ptr,除非您的目标是混淆。它的存在是为了模拟原始指针,但这是继承自 C 的原始指针的错误特征,应该在编写良好的代码(即使在 C 中)中避免。
  • @JamesKanze C 和 C++ 的部分工作是基于 0 == false 的假设,这是无处不在的,你无法避免它,更不用说远离它了。这种联想铭刻在我的程序员大脑中,尽管我已经很久没有接触过 C,而且我想很多其他 C++ 程序员也有这种感觉。
  • *ptr 和 ptr-> 等价于:*get() 和 get()。那不是未定义,你为什么说它未定义?
  • @Epirocks 我认为 OP 意味着当托管指针为空时它是未定义的行为。无论智能指针如何,取消引用 null 都不是定义的行为。
【解决方案2】:

大多数共享指针与此中的普通指针完全相同 尊重。您必须检查是否为空。取决于 功能,你可能想切换到使用

void myFunction( Foo const& foo );

,并通过取消引用指针来调用它(它推动 确保指针不为空的责任 来电者)。

另外,使函数占用可能是不好的做法 一个共享指针除非有一些特殊的所有权 涉及的语义。如果函数只是要使用 函数持续时间的指针,既不改变也不改变 取得所有权,原始指针可能更合适, 因为它对调用者施加的限制较少。 (但是这个 真的很大程度上取决于函数的作用,以及你为什么 使用共享指针。当然,事实上你已经 传递对共享指针的非常量引用假设 你要修改它,所以传递一个共享指针可能是 合适。)

最后,共享指针的不同实现使得它 或多或少难以检查空值。使用 C++11,您可以 使用std::shared_ptr,并将其与nullptr 进行比较 自然如你所料。 Boost实现有点 然而,在这方面被打破了;你不能把它比作 0NULL。您必须要么构造一个空的 boost::shared_ptr 进行比较,或致电 get 并 将生成的原始指针与0NULL 进行比较。

【讨论】:

    【解决方案3】:

    这个问题没有一般的答案。您必须像对待任何其他指针一样对待它。如果您不知道它是否为空,请测试。如果你认为它永远不会为空,assert() 它不为空并直接使用它。

    您引用了shared_ptr,甚至您有一个shared_ptr,对这里没有影响。

    【讨论】:

      【解决方案4】:

      将 shared_ptr 作为引用传递是没有意义的。

      您可以通过boost::shared_ptr&lt;T&gt;.get()获取内部对象并检查nullptr

      也相关:移至标准 :)

      编辑:这是实现:http://www.boost.org/doc/libs/1_55_0/boost/smart_ptr/shared_ptr.hpp 这是一个关于 ref 或 no ref 的 SO 线程:Should I pass a shared_ptr by reference?

      它在 Cx11 时使用移动语义并复制两个整数,否则这比传递引用要慢,但是何时有人处于这种优化级别?

      【讨论】:

      • 没有意义是什么意思?我们对该函数的作用知之甚少。而且您不需要get() 来检查是否为空。
      • 智能指针的整个设计是快速被复制的概念。在 Cx11 中,它使用移动语义,在此之前它基本上复制两个整数,如 shared_ptr 实现中所述。这实际上不应该对性能产生影响。如果没有 .get() 你是对的,应该可以对 null 进行测试。
      • "将 shared_ptr 作为参考传递是没有意义的。" - [需要引用]。您可以通过 const 引用(即“明确模块的 API 不影响值”)或通过引用(即“将其视为输出变量”)传递。传递 (const) 引用可能是由编码约定、技术原因(“模板专业化接收参数作为 const 引用”)等强制要求的。
      • @utnapistim 这个问题之前有人问过:stackoverflow.com/questions/8385457/…
      • @Angew 使用boost::shared_ptr,要么需要get,要么需要构造一个空的boost::shared_ptr 仅用于比较,或者需要使用混淆隐式转换。使用get 可能是最好的(或最不坏的)解决方案。
      猜你喜欢
      • 1970-01-01
      • 2020-08-12
      • 2011-10-29
      • 2015-10-04
      • 2010-10-03
      • 2021-03-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多