首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有理由用原始指针来做RAII吗?C++11/14

有理由用原始指针来做RAII吗?C++11/14
EN

Stack Overflow用户
提问于 2014-06-25 16:25:34
回答 3查看 1.2K关注 0票数 4

是否有理由在C++11/14中仍然使用原始指针(用于托管资源)?

类中的资源成员变量是否应该保存在自己的智能指针中,用于自动RAII,而不需要析构函数中的清理?

智能指针的实现是否内联为这样做没有开销?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-06-25 16:50:00

是否有理由在C++11/14中仍然使用原始指针(用于托管资源)?

我认为“管理资源”指的是“拥有的资源”。

是的,理由如下:

  1. 当你在你的问题中推断的时候,有时你想要引用一个对象或者没有,它会随着时间的推移而改变。在这种情况下,您必须使用原始指针,因为在这个特定的情况下,现在别无选择。稍后可能会有这样的建议,即添加一个“哑”不拥有指针,它只是澄清了指针的作用(观察/引用,而不是自己的)。同时,如果可以的话,建议避免新/删除,并且只使用“引用而不拥有”类型的可重新分配的引用。
  2. 您仍然需要实现非原始指针和任何低级RAII构造的原始指针。并不是每个人都需要在基本库上工作,但当然,如果需要,那么您就需要使用基本构造。例如,在我的领域中,我经常需要以不同的方式建立自定义的“对象池”系统。在实现中的某个时刻,您必须操作尚未成为对象的原始内存,因此您需要使用原始指针来处理它。
  3. 在与C接口通信时,除了将原始指针传递给接受它们的函数外,您别无选择。许多C++开发人员必须这样做,所以只有在代码的某些非常特定的区域才能使用它们。
  4. 大多数使用C++的公司都没有使用C++的“现代C++”体验,它们使用的代码使用了很多不必要的指针。因此,大多数时候,当你在代码库中添加代码时,你可能会因为公司的代码环境、政治、同行压力和惯例而被迫使用指针,在一个更“现代的c++”使用类型的公司中,它不会通过同行评审。因此,在选择技术时也要考虑political/historic/social/knowledge-base-of-coworkers上下文。或者确保你工作的公司/项目与你的做事方式相匹配(这可能更难)。

类中的资源成员变量是否应该保存在自己的智能指针中,用于自动RAII,而不需要析构函数中的清理?

在最好的情况下,资源成员变量应该只是成员,而不是明显的指针,甚至不是智能指针。智能指针是代码操作原始指针和纯RAII样式之间的“桥梁”。如果您完全控制了一些代码,并且它是新代码,则完全可以避免在您的接口中使用任何智能指针。不过,您可能在实现中需要它们。请记住,没有实际的规则,只有关于如果您

智能指针的实现是否内联为这样做没有开销?

标准智能指针的实现是尽可能高效的,所以是的,它们的大部分代码都是内联的。然而,他们并不总是自由的,这取决于他们到底做了什么。例如,几乎在所有情况下,unique_ptr都是一个原始指针,只需对其使用地点进行额外检查。所以它是“免费的”。另一方面,shared_ptr必须维护有多少其他shared_ptr引用同一个对象的计数器。该计数器可以在多个执行shared_ptr副本的线程上更改,因此它必须是原子的。更改原子计数器的值并不总是免费的,您应该始终假定,与复制原始指针相比,存在更高的成本。

所以“视情况而定”。

只是:

  • 尽可能多地使用RAII,而不暴露任何类型的指针在您的接口(聪明与否);
  • 如果必须使用拥有指针,则在实现中使用标准智能指针;
  • 仅当您需要引用对象、null或其他随时间变化的对象时,才使用原始指针,而不需要拥有它们;
  • 避免接口中的原始指针,除非允许传递可选对象(当nullptr是正确的参数时);

从用户的角度来看,您将以代码结束,这些代码似乎不操作指针。如果您有几层代码遵循这些规则,代码将更容易遵循和高度可维护。

关于“When to use references vs. pointers”的相关说明

避免指针,直到你不能。

还要注意的是,肖恩的父母在他最近的谈话中也认为智能指针是原始指针。它们确实可以封装为价值语义类型的实现细节,与实际操作的概念相对应。此外,在实现中使用类型擦除技术,但从不向用户公开它们有助于某些库结构的可扩展性。

票数 5
EN

Stack Overflow用户

发布于 2014-06-25 16:42:32

那得看情况。如果该对象是由另一个对象完全拥有、构造和销毁的,那么在另一个对象中使用std::unique_ptr是一个很好的理由。如果您有一个拥有多个此类对象的对象,所有这些对象都在构造函数中动态分配,那么您必须做一些事情;如果通常的智能指针的语义不合适(通常是这样),那么您就必须发明一些东西:例如,在图的情况下,您可以将根指针放在基类中(将其初始化为null),并让基类的析构函数从根开始清理图形。

当然,除非您的类具有某种动态结构(如图),否则您可能会问自己为什么要首先使用动态分配。有一些特殊情况(例如,拥有的对象是多态的,其实际类型取决于构造函数的参数),但在我的经验中,它们并不常见。实际上,在很多情况下,智能指针可以在对象中使用,更不应该使用。

票数 0
EN

Stack Overflow用户

发布于 2014-06-25 16:43:29

RAII不仅仅是结束新的和删除--智能指针是RAII的一种形式,但是RAII不仅仅是这样。RAII的一个好选择是,当您拥有任何类型的镜像功能时:新/删除、初始化/拆卸、停止/启动。因此,您的资源仍然应该有自己的RAII类--一个在自己的析构函数中执行清理功能的类。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24413976

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档