问题标签 [raii]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - boost::shared_?? 对于非指针资源
基本上我需要对不直接等同于指针/地址语义的某些资源(如整数索引)进行引用计数;基本上我需要传递资源,并在计数达到零时调用某些自定义函数。此外,对资源的读/写访问不是简单的指针取消引用操作,而是更复杂的操作。我不认为 boost::shared_ptr 适合这里的账单,但也许我错过了我可能使用的其他一些 boost 等效类?
我需要做的例子:
python - Python 中的 RAII - 离开作用域时自动销毁
我一直在尝试在 Python中找到RAII 。资源分配是初始化是 C++ 中的一种模式,对象在创建时就被初始化。如果失败,则抛出异常。这样,程序员就知道对象永远不会处于半构建状态。Python 可以做到这一点。
但 RAII 也适用于 C++ 的范围规则,以确保对象的迅速销毁。一旦变量从堆栈中弹出,它就会被销毁。这可能发生在 Python 中,但前提是没有外部或循环引用。
更重要的是,对象的名称仍然存在,直到它所在的函数退出(有时更长)。模块级别的变量将在模块的整个生命周期内一直存在。
如果我做这样的事情,我想得到一个错误:
我可以在使用后手动删除名称,但这会非常难看,并且需要我自己努力。
在这种情况下,我希望它做我的意思:
Python 做了一些作用域,但不是在缩进级别,只是在功能级别。要求我创建一个新函数只是为了限定变量以便我可以重用名称似乎很愚蠢。
Python 2.5 有“with”语句
,但这需要我明确地放入__enter__
和__exit__
函数,并且通常似乎更倾向于清理文件和互斥锁等资源,而不管退出向量如何。它对范围界定没有帮助。还是我错过了什么?
我搜索了“Python RAII”和“Python 范围”,但找不到任何直接且权威地解决该问题的内容。我查看了所有的 PEP。这个概念似乎没有在 Python 中得到解决。
我是一个坏人,因为我想在 Python 中使用范围变量吗?那是不是太不像 Pythonic 了?
我不是在摸索吗?
也许我正试图消除语言动态方面的好处。有时想要强制执行范围是自私的吗?
我是否因为希望编译器/解释器捕捉我疏忽的变量重用错误而懒惰?嗯,是的,我当然很懒,但我是不是很懒?
c++ - longjmp 和 RAII
所以我有一个库(不是我写的),不幸的是它abort()
用来处理某些错误。在应用程序级别,这些错误是可以恢复的,所以我想处理它们而不是让用户看到崩溃。所以我最终写了这样的代码:
不是很优雅的代码。由于这种模式最终不得不在代码的几个地方重复,我想稍微简化一下,并可能将它包装在一个可重用的对象中。我的第一次尝试涉及使用 RAII 来处理信号处理程序的设置/拆卸(需要完成,因为每个函数需要不同的错误处理)。所以我想出了这个:
当然,这种function
方式更简单,更清晰,但今天早上我想到了一个想法。这能保证工作吗?这是我的想法:
setjmp
在对/的调用之间没有变量是易失的或变化的longjmp
。- 我通常在与 and
longjmp
相同的堆栈帧中找到一个位置,因此我允许代码执行编译器在函数退出点发出的清理代码。setjmp
return
- 它似乎按预期工作。
但我仍然觉得这可能是未定义的行为。你们有什么感想?
c++ - 我应该清理 ivar C++ 向量吗...?
如果一个向量被放置在堆栈中,它将在其自动变量范围的末尾自动销毁。
如果我在一个类中放置了一个向量怎么办?
我应该手动清理它吗?如果是这样,我该怎么办?
c++ - 防止 C++(或 C++0x)中的标头爆炸
可以说具有如下通用代码:
y.hpp:
现在,我们希望能够在我们创建的类(比如 X)中使用 Y。但是,我们不希望 X 的用户必须包含 Y 标头。
所以我们定义了一个类 X,如下所示:
x.hpp:
注意,因为 y_ 是一个指针,我们不需要包含它的实现。
实现在 x.cpp 中,单独编译:
x.cpp:
所以现在我们的客户可以只包含“x.hpp”来使用X,而不需要包含并且必须处理所有的“y.hpp”头文件:
main.cpp:
现在我们可以单独编译main.cpp
和编译了,编译时我不需要包含.x.cpp
main.cpp
y.hpp
但是,对于这段代码,我不得不使用原始指针,此外,我不得不使用删除。
所以这是我的问题:
(1)有没有一种方法可以使 Y 成为 X 的直接成员(而不是指向 Y 的指针),而无需包含 Y 标头?(我强烈怀疑这个问题的答案是否定的)
(2)有没有办法可以使用智能指针类来处理堆分配的 Y?unique_ptr
似乎是显而易见的选择,但是当我改变线路时x.hpp
从:
到:
并包含,并使用 c++0x 模式编译,我收到错误:
那么有没有办法通过使用标准智能指针而不是原始指针以及自定义析构函数中的原始删除来做到这一点?
解决方案:
Howard Hinnant 做对了,我们需要做的就是x.hpp
按照x.cpp
以下方式进行更改:
x.hpp:
x.cpp:
我们很适合使用 unique_ptr。谢谢霍华德!
解决方案背后的理由:
如果我错了,人们可以纠正我,但这段代码的问题是隐式默认构造函数试图默认初始化 Y,因为它对 Y 一无所知,所以它不能这样做。通过明确地说我们将在别处定义一个构造函数,编译器认为“好吧,我不必担心构造 Y,因为它是在别处编译的”。
真的,我应该首先添加一个构造函数,没有它我的程序是错误的。
c++ - 检测析构函数中的活动异常
我有一个类使用 RAII 进行清理,以防出现问题。这意味着该类包含一个标志,告诉它工作是否已完成,如果在调用构造函数时未设置此标志,则它正在执行它的清理任务并产生日志消息。现在我希望这个类变得更加聪明,即它应该找出错误是否发生,因为工作被中止(即抛出异常并且调用了析构函数)或者因为有人滥用这个类并且永远不会实际上完成了工作。这意味着我必须在析构函数中找出异常是否处于活动状态。如果找到一个,我会生成一条日志消息,可能会打印异常的内容,然后重新抛出它。我猜是这样的。
但是我不确定这是否会起作用,因为异常在调用析构函数之前已经处于活动状态并且不是源自try
块。另外,我throw;
在析构函数内部使用了一个,此时抛出异常是一个非常糟糕的主意。所以我不会这样做,除非标准明确保证这种情况是这个规则的例外(不是双关语)(我不知道)。
那么这有可能吗,还是我应该以其他方式处理这种情况?
c++ - 用于句柄的 Win API 包装类
为仅按值传递的句柄编写包装类相对容易。我试图确定最好的方法是封装需要通过地址传递的句柄。
例如,为SC_HANDLE之类的东西编写一个按值传递给QueryServiceConfig()的包装器并不难。可以实现一个成员函数,如.GetHandle()或实现operator()。
问题(至少对我而言)是像RegOpenKeyEx()这样需要HKEY地址的API 函数。
我读过重载运算符 & 通常是一个坏主意。在允许 API 函数访问的同时保持封装(或尽可能多的封装),尤其是资源收集的推荐方法是什么?
c++ - Scopeguard 和参数引用
在这篇文章中的参考支持参数部分,他们指出了参考的问题并提供了解决方案。我的问题是:他们为什么不首先将参数声明为引用?即,而不是:
做: