在现代C++后C++11中使用原始指针
Use of raw pointers in modern C++ post C++11
2014年使用原始指针的主要原因是什么,因为C++11标准现在得到了大多数优秀编译器的良好支持?
我确定了几个场景:
-
您正在扩展大量使用原始指针的遗留代码库,并且希望保持样式的一致性。
-
您使用的库只导出原始指针,但我想您仍然可以使用强制转换。
-
您希望利用指针的功能来提供多个级别的间接寻址。(我对C++11还不够了解,不知道这是否可以通过智能指针或其他技术来实现。)
您认为还有哪些场景适合使用指针?
今天,你甚至会建议学习一般的指针吗?
我可以想象这样的情况:您有一个静态分配的数组,并且希望在高性能代码中使用原始指针对其进行迭代。这仍然没有错。
你的#1是真的。
你的#2可能是不对的:如果你"利用强制转换"将第三方库拥有的原始指针转换为智能指针(意味着本地所有权),那么就出了严重的问题。
你的#3在技术上是正确的,但尽可能避免这种情况。
现在不推荐的是使用指向自己的动态分配内存的原始指针。也就是说,建议避免使用没有智能指针的new
(其必然结果是不需要delete
)。
每个人都反对原始指针,因为泄露它们太容易了
但您可以使用原始指针来指向其他地方拥有的数据。。。只是不要new
/delete
它们。使用std::unique_ptr
或std::shared_ptr
。或者,对于使用std::vector<unsigned char>
的dumb(POD)内存缓冲区,不要自己使用malloc
和free
。
当您需要处理对象的子选择时,可以考虑std::vector<heavy_object*>
,这些对象对于复制来说并不重要,但在其他地方已经存在。你需要指针。
您还需要在函数中为可选参数提供指针,因为您希望能够传递nullptr
,所以引用不会剪切这些参数。
指向连续对象的指针也可以很容易地迭代,而不需要任何。只需要std::iterator
开销++
或--
,就可以了。我经常使用直接指针迭代,而不是begin
、end
。
正如你所了解的那样。。。你会非常需要它们,而且你会正确地使用它们
智能指针用于处理对象所有权问题,但并非所有指针都用于处理对象所有者问题。例如,如果您不打算将所有权传递给某个函数(即您只希望该函数处理指针所寻址的数据),则将原始指针传递给该函数更有意义。
IMHO原始指针仍有其位置
C++11给我们的是管理原始指针寿命的能力,这样我们就不必自己删除它们。
使用原始指针没有错,只要它们由智能指针/指针管理器在正确的范围或框架中进行管理,以确保它们的寿命是正确的。如果这是真的,那么您永远不必删除原始指针,并且您可以在保证其使用寿命的范围/框架内安全地使用它们。
我想说,如果可能的话,如果新对象的寿命应该由给定的范围/帧控制,那么在std::unique_ptr
中存储一个指向新对象的原始指针。完成后,在该范围框内使用原始指针。只是永远不要删除它;
有时,无法从单个范围或帧管理新对象的寿命。在这种情况下,在每个需要独立管理新对象寿命的范围/帧中使用std::shared_ptr
。然后,在每个作用域/帧中,没有理由不使用原始指针,就像std::unique_ptr
管理它一样。
因此,通常没有理由产生智能指针的速度劣势,因为它们的优势之一在于管理新对象的寿命,以确保原始指针的有效性,并在不再需要时自动销毁其对象。
在其他情况下,原始指针是不合适的
例如,当托管指针需要将"所有权"转移到另一个作用域/框架时。这时,您需要负责管理新对象寿命的范围/框架进行更改。在这些情况下,避免像瘟疫一样的原始指针
您认为还有哪些场景适合使用指针?
使用原始指针的主要场景之一是当您有非拥有指针时。通常情况下,引用会起作用,但您希望避免引用的限制(不可重新密封、不可复制)。在这种情况下,可以使用reference_wrapper
类型,但只使用原始指针更简单。智能指针对所有权(创建和销毁对象的人)进行编码,因此,如果没有要编码的所有权(因为这是隐含的),那么原始指针就可以了
为了清楚起见,我刚才解释的典型例子是:
- 需要指向某个不属于它的对象的指针的临时可复制函子
- 数据结构内的内部交叉链接(例如"反向指针")
但需要注意的是,这些东西一般不应该出现在接口中。通常,您可以在接口(例如,库函数和类)中完全避免使用原始指针,而只在内部使用它们,即在库端代码中,而不是在用户端代码中。换句话说,如果您需要使用原始指针,请将它们隐藏起来。
有时还可以看到可选函数参数的原始指针,如果不希望得到结果,可以在其中传递nullptr
。
应该避免的,并且通常可以避免的主要事情是用户端代码中的裸new
/delete
调用。一个典型的好的现代C++库(C++11更是如此)不会出现任何这样的裸露new
/delete
,这是事实。
原始指针本身并不是一个问题,问题在于(1)手动内存管理和(2)所有权管理(如果使用原始指针而不是智能指针,这是有问题的)。
今天,你甚至会建议学习一般的指针吗?
你当然应该学习指针。它们对于理解编程和学习编写库端代码至关重要。原始指针仍然存在于许多库代码的内部,即使你看不到它们。
使用原始指针的常见原因。
- 读取和解析二进制文件
- 直接与硬件交互
- 阵列
- 速度。AFAIK智能指针比原始指针慢,并且有相对安全的方法来使用原始指针。例如,请参阅Chromium的代码库或WebKit的代码库。两者都使用各种类型的跟踪内存,而没有智能指针的全部开销。当然也有局限性
- 从堆栈分配的原始指针构造智能指针
- 将unique_ptr分配给原始指针
- 如何将唯一指针的 std::vector 转换为原始指针的 std::span?
- <Base> <Derived> 具有相同原始指针共享引用的 shared_ptr 和 shared_ptr 实例是否计数?
- C++原始指针和"delete"
- 为什么 C++ 地址中的矢量无法通过原始指针访问
- 如何正确实现具有原始指针的类的复制构造函数?
- 如何在将原始指针移动到基类构造函数之前从unique_ptr中提取原始指针
- 为包含原始指针的对象C++智能指针
- c++:复制、删除和运算符=在原始指针映射中
- C++模板,用于通过常量引用和原始指针传递向量
- C++为什么原始指针不会增加shared_ptr的引用计数?
- 从shared_ptr获取原始指针以将其传递给需要 raw 的函数
- 如何包装多级原始指针以赋予其容器语义
- 为什么我可以通过原始指针而不是shared_ptr来修改对象
- 将原始指针传递给接受unique_ptr作为参数的函数
- 为什么我们不允许将纯引用参数传递给 std::thread,但允许传递原始指针?
- 更改保留指向其字段的原始指针的对象地址
- 从原始指针(衰减的 C 样式数组)和大小生成范围::视图
- 如何在C++代码中灵活使用和替换标准::shared_ptr或标准::unique_ptr或原始指针?