指向以其他方式分配的事物的指针在C++中是否合理安全?
到目前为止,我一直在使用 STL 容器(在一种情况下是数组,但这是另一个问题(来满足我所有的动态内存需求,所以我不需要显式使用 new
关键字。我也一直在轻率地使用普通的 ol' int *foo
类型指针来引用事物。现在我正在阅读有关智能指针的文章(我在 Java 上咬牙切齿,所以我以前从来不必担心这一点(,而传统智慧似乎是"裸指针不好,不要使用它们"。
那么我遇到了多大的麻烦?我可以安全地继续使用裸指针吗,只要它们指向的东西有其他破坏条件?这是我可以侥幸逃脱,但将来应该避免的事情吗?还是一场灾难正在酝酿中,我应该匆忙解决?
指针本身是安全的,不正确使用它们是危险的(你很容易得意忘形(。聪明的指针很漂亮,但有些(shared_ptr
(涉及引用计数,这会导致性能损失。您应该尝试在适用的情况下使用智能指针,但使用指针的 AFAIK 并不被认为是一个可怕的错误。
引用 STL 容器的成员时应小心,因为它们的地址在重新定位期间可能会更改,从而留下奇怪的错误。
说"裸指针不好;不要使用它们",并附上一个小附录:"指出你必须清理的东西"。
如果你有一个对象,而别人有责任摧毁它,那么原始指针绝对没问题。但是,当您负责通过任何清理功能销毁对象时,请始终使用智能指针。此外,对于您不清理的对象,请注意它们在什么条件下被另一个系统函数局部清理,vector
调整大小等。
所有权规则:
- 无所有权:
T*
,并注意何时不能再使用它 - 共享所有权:
shared_ptr<T>
,必要时使用自定义删除器 - 唯一所有权:
unique_ptr<T, Del>
,必要时自定义删除器
始终遵循这些规则,您将永远不会有任何内存泄漏、双重释放、错误的指针访问或任何类似的内存相关错误。
在一个完美的世界里,编写代码的人和维护它的人不会犯任何错误,从来没有,原始指针是惊人的。
不幸的是,事实并非如此。首先,裸指针容易出错,指向一些可以在指针不知道的情况下失效的内存,指针可以别名并更改它们指向的内容。
我们实际上需要聪明的指针来弥补我们的"愚蠢"。至少有些东西必须是"聪明"的:)。
除非你正在做一些非常底层的事情,否则没有必要使用原始指针,因为它们"不那么聪明"。话虽如此,如果你非常小心,并且在你编写代码后使用你的代码的人非常小心(通常情况下情况并非如此(,那么继续使用原始指针,但除此之外,使用智能指针,因为它们只产生很少或没有开销。
unique_ptr<>
没有任何开销,直到您移动它,在这种情况下,它会将一个 NULL 写入内存。 在现代编译器上,这经常被优化出来。
shared_ptr<>
计算引用,并且可能会产生相当大的开销,尤其是在多线程应用程序中使用时,但这可以解决,因此不是一个大问题。
总而言之,没有必要紧急修复原始指针,但我认为不鼓励使用它们。
指针被认为是不好的,因为很容易遇到麻烦。智能指针会自动为您处理一些问题,这使得它们不容易出错。
当你对所有代码拥有绝对控制权时(即,你是项目中唯一的编码人员(,那么只要你遵循基本的内存分配法律和习俗("除非另有说明,否则分配内存的人都会摆脱它"(,使用裸指针是可以的。但是,当您与其他人一起编写代码(即,具有1个以上编码人员的项目(时,就会打开错误和误解的大门。
智能指针负责谁拥有对象(因此谁应该释放它(。他们还可以跟踪使用该对象的最后一个代码何时不再需要它,因此可以在共享分配的数据时安全地释放它。
引用计数的智能指针还为从堆分配内存的类的那些数据成员生成安全的默认复制构造函数和安全的默认复制赋值运算符。他们可以安全地将引用计数智能指针设置为他们正在复制的原始对象,当原始对象或克隆超出范围/被删除时,他们通过智能指针管理和共享的分配内存将留给仍然指向它的另一个对象。裸指针则不然。如果使用裸指针,则必须编写复制赋值运算符和复制构造函数来克隆分配内存的对象,以防止包含/拥有的已分配数据的数据损坏。
当你new
和delete
而不必担心太多时,裸指针是不好的。这种行为可能会导致您出现非常奇怪的错误。我的建议是,当你必须使用堆上分配的几个指针和对象时,使用内存泄漏检查器 Valgrind 来学习。
然后是一些简单的规则,当您使用new []
实例化数组时,您始终必须delete []
删除它们,相反,当您使用new
实例化单个对象时,请始终调用delete
。
请记住避免混合new
- delete
与malloc
- free
或new[]
- delete[]
因为这些函数不是为相互协作而设计的,例如永远不要这样做:
int *a = (int*)malloc(10*sizeof(int));
delete a;
但是这个
int *a = new int[10];
delete[] a;
正如Tibor所说,指针的使用本身并不坏,但一如既往,"权力越大,责任越大":P