- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以,我一直在做一些库的开发,并陷入了困境。图书馆是私有(private)的,所以我不能分享它,但我觉得这可能是一个有意义的问题。
困境本身表现为一个问题,即为什么库中没有资源处理类的默认构造函数。该类处理一个特定的文件结构,这并不重要,但让我们调用类 Quake3File。
然后请求是实现默认构造函数和“适当的”打开/关闭方法。我的思路是 RAII 风格,也就是说,如果您创建类的实例化,则必须为其提供一个它处理的资源。这样做可以确保所有成功构建的句柄都是 有效 和 IMO 消除了一整类错误。
我的建议是保留一个(智能)指针,然后用户不必实现打开/关闭并打开一 jar 蠕虫,而是在免费商店中创建类以“打开”它并在您想要删除时删除“关闭”它。当它超出范围时,使用智能指针甚至会为您“关闭”它。
这就是冲突的来源,我喜欢模仿类的 STL 设计,因为这使我的类更易于使用。由于我正在创建一个主要处理文件的类,如果我以 std::fstream 为指导,那么我不确定是否应该实现默认构造函数。整个 std::fstream 层次结构的事实使我指向是,但我自己的想法是否。
所以问题或多或少是:
最佳答案
可以说有两类 RAII 类:“始终有效”和“可能为空”类。标准库(或接近标准的库,如 Boost)中的大多数类都属于后一类,我将在这里解释几个原因。 “始终有效”是指必须构造为有效状态的类,然后在销毁之前保持有效。我所说的“可能为空”是指可以在无效(或空)状态下构造的类,或者在某个时刻变为无效(或空)的类。在这两种情况下,RAII 原则仍然存在,即类处理资源并实现对其的自动管理,如在销毁时释放资源。因此,从用户的角度来看,他们都享有相同的资源泄漏保护。但是有一些关键的区别。
首先要考虑的是,我能想到的几乎所有资源的一个关键方面是资源获取总是会失败。例如,您可能无法打开文件、无法分配内存、无法建立连接、无法为资源创建上下文等。因此,您需要一种方法来处理这种潜在的故障。在“始终有效”的 RAII 类中,您别无选择,只能通过从构造函数抛出异常来报告该失败。在“可能为空”的类中,您可以选择通过使对象处于空状态来报告该失败,也可以抛出异常。这可能是 IO-streams 库使用该模式的主要原因之一,因为他们决定将异常抛出作为其类中的一个可选功能(可能是因为许多人不愿过多地使用异常)。
要考虑的第二件事是“始终有效”的类不能是可移动的类。将资源从一个对象移动到另一个对象意味着使源对象“为空”。这意味着“始终有效”的类必须是不可复制和不可移动的,这可能会给用户带来一些烦恼,并且还会限制您自己提供易于使用的界面的能力(例如,工厂函数等)。这也将要求用户在需要移动对象时在 freestore 上分配对象。
(编辑)
正如下面 DyP 所指出的,只要您可以将对象置于可破坏状态,您就可以拥有一个“始终有效”的可移动类。换句话说,该对象的任何其他后续使用都将是 UB,只有销毁才会表现良好。然而,强制执行“始终有效”资源的类仍然不够灵活,并且会给用户带来一些烦恼。
(结束编辑)
显然,正如您所指出的,“始终有效”的类通常在其实现中更加万无一失,因为您无需考虑资源为空的情况。换句话说,当你实现一个“可能为空”的类时,你必须在每个成员函数中检查资源是否有效(例如,文件是否打开)。但请记住,“易于实现”并不是规定特定界面选择的正当理由,界面面向用户。但是,这个问题对于用户端的代码也是如此。当用户处理一个“可能为空”的对象时,他总是必须检查有效性,这会变得很麻烦且容易出错。
另一方面,一个“永远有效”的类将不得不完全依赖异常机制来报告它的错误(即,错误条件不会因为“永远有效”的假设而消失),因此可能会带来一些有趣的挑战在其实现中。通常,您必须为涉及该类的所有函数(包括实现代码和用户端代码)提供强大的异常安全保证。例如,如果您假定对象“始终有效”,并且您尝试执行失败的操作(例如读取文件末尾之外),那么您需要回滚该操作并将对象恢复到其原始有效状态,以强制执行您的“始终有效”的假设。通常,用户会在相关时被迫做同样的事情。这可能与您正在处理的资源类型兼容,也可能不兼容。
(编辑)
正如下面 DyP 所指出的,这两种 RAII 类之间存在灰色阴影。所以,请注意,这个解释是在描述两个极点或两个一般分类。我并不是说这是非黑即白的区别。显然,许多资源具有不同程度的“有效性”(例如,无效的文件处理程序可能处于“未打开”状态或“到达文件结尾”状态,这可以以不同的方式处理,即,像“始终打开”,“可能在 EOF”,文件处理程序类)。
(结束编辑)
Should resource handles really have default constructors?
What is a good way implement a default constructor on a class that deals with files? Just set the internal state to an invalid one and if a user missuses it by not giving it a resource have it result in undefined behavior? Seems strange to want to take it down this route.
Why does the STL implement the fstream hierarchy with default constructors? Legacy reasons?
关于c++ - 资源句柄 - 禁止默认构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20383993/
我正在尝试使用 npmpublish 命令发布包。但我每次都会收到此错误。 npm ERR! code E403 npm ERR! 403 Forbidden - PUT https://regist
我在 WAMP 上访问我的本地主机(最后是 phpmyadmin)时遇到问题。 当我输入 localhost或 http://127.0.0.1进入我的浏览器,我收到以下消息: Forbidden Y
我正在尝试发送 $ajax,并且我已经得到了它,但是我必须使用我的表单发送文件,无论是否相同,都没关系。尚未找到 csrf token ,并且出现错误。 我的 JavaScript $(doc
我有一个奇怪的问题,我试图使用请求模块废弃某些页面,但这样做时我收到 403 访问被拒绝。但我完全能够使用 Node 的curl 模块来完成此操作。但互联网上的人们认为,它比请求模块更需要性能,因为我
所以,我正在制作一个公共(public)的不和谐机器人,但我的脚本的一部分有问题。我的 kick/ban 命令是用来完成的 $ban @user 它必须在 ping 中完成。由于这是公开的,我真的很想
我在负载均衡器后面有 2 个服务器。此 LB 上配置了 SSL。将近 50 个不同的客户端能够成功连接到我的网站,除了 1 个客户端从浏览器收到禁止 (403) 消息。 经过一番调查,我发现他在代理服
1、禁止计算局部梯度 torch.autogard.no_grad: 禁用梯度计算的上下文管理器。 当确定不会调用Tensor.backward()计算梯度时,设置禁止计算梯度会减少内存消耗。
如果 Moose 的构造函数调用中有额外的参数不是属性,有没有办法死?例如,这个: package Shoe; use Moose; has 'size' => (is => 'ro', isa =
在服务器上,安装了 Nginx。 Let's Encrypt 在 www.domain.com 上运行良好,但不适用于 static.domain.com 使用 PuTTY,当我输入时:sudo le
我使用 emacs 来编辑所有内容。在我的一些 LateX 文档中,我想在编辑表格和代码时自动禁用自动填充模式。基本上,我想要两个标签,例如: %%% BEGIN NO FILL %%%
通过 Nuget,我将 WindowsAzure.Storage 升级到 8.1.1。 然后,我下载了 AzureStorageEmulator 5.1.0.0 客户端。 我的连接字符串: UseDe
Qt documentation说,信号的返回值是不可能的: Signals are automatically generated by the moc and must not be implem
编辑版本 我有一个关于 GPG 的问题,但我写了所有的过程,也许它会对某人有所帮助。 我想:禁止 GPG 命令中的密码提示。 我不想:使用 -c 选项(--对称)。 我有 2 个系统 Linux 和
现在的想法是这样的:在 Java 中为 octalIntegerLiteral我有一个规则 octalNumeral, (integerTypeSuffix optional) 但我想得到一个数字作为
我在 Python 项目中所有模块的开头使用以下内容: import setup_loggers setup_loggers是一个可以做到这一点的模块。 import语句确保无论首先加载哪个模块,记录
我刚刚下载了最新版本的 XAMPP,PHP 版本为 7.2.4。我为 HTML 表单做了一个非常简单的 PHP 验证,当我按下提交时,它会出现以下内容: Access forbidden!You do
我已经成功运行 Vagrant 大约一个星期了。昨晚我运行了 vagrant reload,现在我无法再访问我的网站。 VirtualBox 版本 4.2.16 Vagrant 版本 1.2.7 我的
我使用以下 JavaScript 代码在完成 ajax 后播放音频: $(document).ready(function () { $.ajaxSetup(
我有一个似乎可以在互联网上运行的应用程序。但我接到了一位最终用户的电话,他在使用website时遇到困难。 我要求她发送控制台错误的屏幕截图并收到以下信息: 从 stackoverflow 搜索来看,
我在尝试提交到 svn 存储库时遇到此错误: svn: MKACTIVITY of '/svn/Demo/!svn/act/e2e65cfa-...4165f': 403 Forbidden (htt
我是一名优秀的程序员,十分优秀!