【问题标题】:Once you've adopted boost's smart pointers, is there any case where you use raw pointers?一旦你采用了 boost 的智能指针,有没有使用原始指针的情况?
【发布时间】:2008-12-12 16:47:15
【问题描述】:

我很好奇,因为我开始采用更多的 boost 习语以及似乎是最佳实践的最佳实践那些没有接触过“现代 C++”的人?

【问题讨论】:

    标签: c++ boost smart-pointers


    【解决方案1】:

    我几乎不使用shared_ptr,因为我通常避免共享所有权。因此,我使用boost::scoped_ptr 之类的东西来“拥有”一个对象,但对它的所有其他引用都将是原始指针。示例:

    boost::scoped_ptr<SomeType> my_object(new SomeType);
    some_function(my_object.get());
    

    但是some_function 会处理一个原始指针:

    void some_function(SomeType* some_obj)
    {
      assert (some_obj);
      some_obj->whatever();
    }
    

    【讨论】:

    • 击败我 - 我要说的是,通过原始指针传递可以按照约定来暗示被调用者不会保留对对象的引用(或者至少不会以某种方式影响资源管理)。
    • 如何在不影响资源管理的情况下保留对对象的引用?一旦资源被销毁,该引用的保留者现在必须意识到这一事实,对吧?
    • 一切都与范围有关。将所有者放在将要使用对象的最外层范围内,然后在该范围内将指针传递给它。任何引用都不允许存在于比所有者更广泛的范围内,因此它保证指向一个有效的对象。
    • 为什么不通过引用传递scoped_ptr?
    • 参考人!除非您想明确允许使用 nullptr 调用函数,否则我会说引用是要走的路。当编译器很乐意为您执行错误时,为什么要在运行时捕获错误?
    【解决方案2】:

    我脑子里只有几个:

    • 在内存映射文件中导航。
    • 您必须过度分配的 Windows API 调用(如 LPBITMAPINFOHEADER)。
    • 您在任意内存(VirtualQuery() 等)中四处游荡的任何代码。
    • 几乎任何时候您都在指针上使用 reinterpret_cast。
    • 任何时候使用placement-new。

    这里的共同点是“任何情况下,您需要将一块内存视为您拥有分配控制权的资源以外的东西”。

    【讨论】:

    • 每当我需要分配内存时(比如在最后保存一个带有额外字节的 BITMAPINFOHEADER),如果可能的话,我会使用 std::vector ,那么就不用担心删除了,如果Windows API 会告诉我分配的内存不够,std::vector::resize() 很好。
    • 当然。如果可能,您仍然可以使用标准容器或智能指针来管理底层内存。关键是当您要与 Windows API 交谈时,您将转换为原始指针,这就是原始问题所问的内容。
    • 也用于与“外部”的接口。如果你的用户请求一个缓冲区,那么它会得到一个缓冲区,而不是智能指针。
    【解决方案3】:

    这些天来,我几乎放弃了对原始指针的所有使用。我什至开始在我们的代码库中查找使用原始指针的地方,并将它们切换为智能指针变体。通过这个简单的操作,我能够删除多少代码,真是令人惊讶。在原始 C++ 指针的生命周期管理上浪费了太多代码。

    我不使用指针的唯一地方是用于与我无法控制的其他代码库的几个互操作场景。

    【讨论】:

      【解决方案4】:

      我发现“现代”C++ 和旧* 的主要区别在于谨慎使用类不变量和封装。组织良好的代码自然倾向于有更少的指针飞来飞去。在 shared_ptrs 中游泳时,我几乎和在新闻和删除中一样紧张。

      我期待 C++0x 中的 unique_ptr。我认为这将消除仍然在野外漫游的少数(智能)指针。

      *不幸的是仍然很常见

      【讨论】:

        【解决方案5】:

        当然,在处理遗留库或 API 时,您需要传递一个原始指针,尽管您可能只是暂时从智能指针中提取它。

        事实上,将原始指针传递给函数总是安全的,只要函数不尝试将指针的副本保留在全局变量或成员变量中,或者尝试删除它。有了这些限制,函数就不会影响对象的生命周期,智能指针的唯一原因是管理对象的生命周期。

        【讨论】:

          【解决方案6】:

          我仍然在资源敏感代码或其他需要占用空间很小的代码中使用常规指针,例如某些异常,我不能假设任何数据都是有效的,并且还必须假设我的内存也快用完了。

          托管内存几乎总是优于原始内存,因为这意味着您不必在正确的位置处理它,但仍然可以很好地控制指针的构造和销毁点。

          哦,还有另一个地方可以使用原始指针:

          boost::shared_ptr<int> ptr(new int);
          

          【讨论】:

          • 我认为 boost: 指针类没有开销?编译器不会优化所有内容吗?
          • 作用域指针类的开销并不大,但它必须存在,共享指针需要引用计数和相关机制。不过,我始终遵循规则 1;先配置文件,然后优化。
          • 无法想象在 15 年的 C++ 编码中我曾经需要在堆上显式分配单个 int。 int:s 数组是另一回事,但总会有 std::vector.
          【解决方案7】:

          我仍然在具有内存映射 IO 的设备上使用原始指针,例如嵌入式系统,在这些设备上拥有智能指针并没有真正意义,因为您永远不需要或无法delete 它。

          【讨论】:

            【解决方案8】:

            如果你有循环数据结构,例如,A 指向 B,B 指向 A,你不能天真地为 A 和 B 使用智能指针,因为那样对象只会被释放额外的工作。要释放内存,您必须手动清除智能指针,这与删除智能指针一样糟糕。

            您可能会认为这种情况并不经常发生,但假设您的 Parent 对象具有指向一堆 Child 对象的智能指针。在某个地方,有人需要查找父级的子级,因此他们向子级添加了一个智能指针成员,该成员指向父级。默默地,内存不再被释放。

            需要一些小心。智能指针不等同于垃圾回收。

            【讨论】:

            • 这就是 boost::weak_ptr 的用途,如果你有的话。所以你仍然可以使用智能指针而不是原始指针,只是不是所有的智能指针都是 shared_ptr。
            • 绝对 boost::weak_ptr 是解决循环引用问题的另一种方法,但我认为我的观点仍然成立:你必须注意而不是盲目地使用你拥有的任何智能指针。
            • 我想我假设当提问者说“采用 boost 的智能指针”时,他的意思是所有这些,正确使用,而不仅仅是 shared_ptr 用于所有内容。你是对的,不是所有的读者都会喜欢这个:-)
            【解决方案9】:

            我正在编写必须与 Objective C 共存的 C++(使用 Objective C++ 进行桥接)。 因为声明为 Objective C++ 类的一部分的 C++ 对象没有调用构造函数或析构函数,所以不能真正将它们保存在智能指针中。

            所以我倾向于使用原始指针,尽管通常使用 boost::intrustive_ptr 和内部引用计数。

            【讨论】:

            • 这是正确的吗?我对doco的阅读说,调用了无参数构造函数,并在销毁Objective C对象时调用了析构函数。自从您发布以来,情况可能已经发生了变化/改善。
            • 自从我发布以来,情况已经发生了变化/改进 :-) 实际上,就在我发布之前 - 我已经有点过时了。
            【解决方案10】:

            我不会这样做,但您需要原始指针来实现,例如,链表或图表。但是使用std::list&lt;&gt; 或boost::graph&lt;&gt; 会更聪明。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2014-07-25
              • 1970-01-01
              • 1970-01-01
              • 2016-08-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多