在现代C++后C++11中使用原始指针

Use of raw pointers in modern C++ post C++11

本文关键字:原始 指针 C++11 C++      更新时间:2023-10-16

2014年使用原始指针的主要原因是什么,因为C++11标准现在得到了大多数优秀编译器的良好支持?

我确定了几个场景:

  1. 您正在扩展大量使用原始指针的遗留代码库,并且希望保持样式的一致性。

  2. 您使用的库只导出原始指针,但我想您仍然可以使用强制转换。

  3. 您希望利用指针的功能来提供多个级别的间接寻址。(我对C++11还不够了解,不知道这是否可以通过智能指针或其他技术来实现。)

您认为还有哪些场景适合使用指针?

今天,你甚至会建议学习一般的指针吗?

我可以想象这样的情况:您有一个静态分配的数组,并且希望在高性能代码中使用原始指针对其进行迭代。这仍然没有错。

你的#1是真的。

你的#2可能是不对的:如果你"利用强制转换"将第三方库拥有的原始指针转换为智能指针(意味着本地所有权),那么就出了严重的问题。

你的#3在技术上是正确的,但尽可能避免这种情况。

现在不推荐的是使用指向自己的动态分配内存的原始指针。也就是说,建议避免使用没有智能指针的new(其必然结果是不需要delete)。

每个人都反对原始指针,因为泄露它们太容易了

但您可以使用原始指针来指向其他地方拥有的数据。。。只是不要new/delete它们。使用std::unique_ptrstd::shared_ptr。或者,对于使用std::vector<unsigned char>的dumb(POD)内存缓冲区,不要自己使用mallocfree

当您需要处理对象的子选择时,可以考虑std::vector<heavy_object*>,这些对象对于复制来说并不重要,但在其他地方已经存在。你需要指针。

您还需要在函数中为可选参数提供指针,因为您希望能够传递nullptr,所以引用不会剪切这些参数。

指向连续对象的指针也可以很容易地迭代,而不需要任何std::iterator开销。只需要++--,就可以了。我经常使用直接指针迭代,而不是beginend

正如你所了解的那样。。。你会非常需要它们,而且你会正确地使用它们

智能指针用于处理对象所有权问题,但并非所有指针都用于处理对象所有者问题。例如,如果您不打算将所有权传递给某个函数(即您只希望该函数处理指针所寻址的数据),则将原始指针传递给该函数更有意义。

IMHO原始指针仍有其位置

C++11给我们的是管理原始指针寿命的能力,这样我们就不必自己删除它们。

使用原始指针没有错,只要它们由智能指针/指针管理器在正确的范围或框架中进行管理,以确保它们的寿命是正确的。如果这是真的,那么您永远不必删除原始指针,并且您可以在保证其使用寿命的范围/框架内安全地使用它们。

我想说,如果可能的话,如果新对象的寿命应该由给定的范围/帧控制,那么在std::unique_ptr中存储一个指向新对象的原始指针。完成后,在该范围框内使用原始指针。只是永远不要删除它;

有时,无法从单个范围或帧管理新对象的寿命。在这种情况下,在每个需要独立管理新对象寿命的范围/帧中使用std::shared_ptr。然后,在每个作用域/帧中,没有理由不使用原始指针,就像std::unique_ptr管理它一样。

因此,通常没有理由产生智能指针的速度劣势,因为它们的优势之一在于管理新对象的寿命,以确保原始指针的有效性,并在不再需要时自动销毁其对象。

在其他情况下,原始指针是不合适的

例如,当托管指针需要将"所有权"转移到另一个作用域/框架时。这时,您需要负责管理新对象寿命的范围/框架进行更改。在这些情况下,避免像瘟疫一样的原始指针

您认为还有哪些场景适合使用指针?

使用原始指针的主要场景之一是当您有非拥有指针时。通常情况下,引用会起作用,但您希望避免引用的限制(不可重新密封、不可复制)。在这种情况下,可以使用reference_wrapper类型,但只使用原始指针更简单。智能指针对所有权(创建和销毁对象的人)进行编码,因此,如果没有要编码的所有权(因为这是隐含的),那么原始指针就可以了

为了清楚起见,我刚才解释的典型例子是:

  • 需要指向某个不属于它的对象的指针的临时可复制函子
  • 数据结构内的内部交叉链接(例如"反向指针")

但需要注意的是,这些东西一般不应该出现在接口中。通常,您可以在接口(例如,库函数和类)中完全避免使用原始指针,而只在内部使用它们,即在库端代码中,而不是在用户端代码中。换句话说,如果您需要使用原始指针,请将它们隐藏起来。

有时还可以看到可选函数参数的原始指针,如果不希望得到结果,可以在其中传递nullptr

应该避免的,并且通常可以避免的主要事情是用户端代码中的裸new/delete调用。一个典型的好的现代C++库(C++11更是如此)不会出现任何这样的裸露new/delete,这是事实。

原始指针本身并不是一个问题,问题在于(1)手动内存管理和(2)所有权管理(如果使用原始指针而不是智能指针,这是有问题的)。

今天,你甚至会建议学习一般的指针吗?

你当然应该学习指针。它们对于理解编程和学习编写库端代码至关重要。原始指针仍然存在于许多库代码的内部,即使你看不到它们。

使用原始指针的常见原因。

  1. 读取和解析二进制文件
  2. 直接与硬件交互
  3. 阵列
  4. 速度。AFAIK智能指针比原始指针慢,并且有相对安全的方法来使用原始指针。例如,请参阅Chromium的代码库或WebKit的代码库。两者都使用各种类型的跟踪内存,而没有智能指针的全部开销。当然也有局限性