C++ RAII 问题
因此,据我了解,要正确实现 RAII,如果我在哪里调用 CreateFont,我会将其包装在一个类中,在构造函数中使用 CreateFont 并使用 DeleteObject< /code> 在析构函数中,因此当它超出范围时它会清理它。
第一个问题是,我最终不会有很多课程这样做吗?特别是因为该类只有构造函数和析构函数。
第二个问题是,如果我在 WndProc 中调用 CreateFont 类,它会不断超出范围,该怎么办?那么我是否应该在 WndMain 中对 CreateFont 或 LoadBitmap 进行所有调用? 我习惯于在 WM_CREATE
中调用这些函数并在 WM_DESTROY
中清理它们。
So as I understand it to implement RAII properly, if I where to call CreateFont
, I'd wrap that in a class with CreateFont
in the constructor and DeleteObject
in the destructor, so it cleans it up when it goes out of scope.
First question is, won't I end up with ALOT of classes doing that? Especially since the class only has a constructor and destructor.
Second question is, what if I'm calling the CreateFont class in the WndProc, that goes out of scope constantly. So am I supposed to do all my calls to CreateFont
or like LoadBitmap
in the WndMain?
I'm used to calling those functions in WM_CREATE
and cleaning them up in WM_DESTROY
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
使用模板可以帮助您避免大量重复性工作。例如,如果您使用
boost::shared_ptr
您可以这样做:这可以节省您编写自定义类来管理资源的时间。如果您无法使用 boost 和 TR1 或更新版本,您仍然可以自己实现类似和通用的东西来提供帮助。
boost::shared_ptr 是正确的引用计数,因此,如果您想在某个地方创建它并“促进”它的寿命更长,您可以通过在它消失之前将其复制到寿命更长的地方来实现。
You can avoid a lot of repetitious work by using a template to help you. For example if you use
boost::shared_ptr
you can do:Which saves you writing a custom class to manage the resource. If boost and TR1 or newer aren't available to you it's still possible to implement something similar and generic yourself to assist.
boost::shared_ptr
is reference counted properly, so if you want to create it somewhere and "promote" it to live longer later you can do so by copying it somewhere longer lived before it dies.是的,但有几点需要考虑:
HANDLE
对象的 Win32 函数,并且它们都是封闭的同样的方式(使用CloseHandle
),因此您可以重复使用相同的类,将其存储在不会过早超出范围的位置。 :)
在这里,智能指针可能再次有用。例如,只要至少有一个
shared_ptr
指向该字体,就可以使用shared_ptr
来使该字体保持活动状态。然后,您可以简单地将其从函数中传递到某个常见的长期存在的位置。否则,只要您为 RAII 类实现复制构造函数和赋值运算符(在 C++11 中,您可能希望实现移动构造函数和移动赋值),就可以将其安全地复制(或移动)到您想要放置的任何位置它,即使它是在较小的范围内创建的。
Yes, but there are few points to consider:
HANDLE
objects, and they're all closed the same way (withCloseHandle
), so you could reuse the same class for those.Store it in a location where it won't go out of scope prematurely. :)
Here, smart pointers might be useful again. For example,
shared_ptr
could be used to keep the font alive as long as there's at least oneshared_ptr
pointing to it. Then you can simply pass it out of the function to some common longer-lived location.Otherwise, as long as you implement copy constructor and assignment operator (in C++11 you might want to implement move constructor and move assignment instead) for your RAII class, it can be copied (or moved) safely to wherever you want to put it, even if it was created in a smaller scope.
如果您不喜欢需要为每种不同类型的对象创建的类数量,您可以创建一个 RAII 类,该类在构造函数中采用 HGDIOBJ 参数并调用在析构函数中删除Object。该类可用于所有不同的 GDI 对象。例如:
对于需要在内存中保留的时间超过函数作用域的项目,您必须将它们放在全局级别。
If you don't like the number of classes you'd need to create for each different type of object, you can create a single RAII class that takes a HGDIOBJ parameter in the constructor and calls DeleteObject in the destructor. This class can then be used for all the different GDI objects. For example:
For items that need to remain in-memory for longer than the function scope, you'll have to put these at the global level.
如果您打算使用可靠的 RAII,有一些选项可以减少您需要的类的数量 - 例如,一些 boost 智能指针(特别是 shared_ptr)允许您提供自己的函数,以便在指针超出范围时调用范围。
否则,是的 - 您将为任何需要显式释放的资源提供一个类 - 虽然这在代码方面是一个痛苦,但从长远来看,它将节省您大量的调试时间(特别是在小组项目中)。不过,我仍然建议根据您自己对情况的感受来使用 RAII - 在任何地方使用它是一个很棒的主意,但有时在转换旧代码时,修复所有调用链可能需要大量工作使用它。
另一件事 - 我不太熟悉你正在使用的 GUI 逻辑,所以我不会专门去那里......但你必须研究你的资源应该如何复制以及它们应该复制多长时间被维护。您的 RAII 容器将采用引用计数,还是具有值(复制)语义?只要您可以在代码中传递对原始资源的引用,像shared_ptr这样的引用计数智能指针就可以经常解决有关资源重新创建的问题。
If you're going for solid RAII, there are some options for reducing the number of classes you'll need - for example, some boost smart pointers (shared_ptr specifically) allow you to provide your own function to call when the pointer goes out of scope.
Otherwise, yes - you'll have a class for any resource which requires explicit freeing - and while it's a pain in the butt code-wise, it will save you massive time in debugging in the long run (especially in group projects). I'd still say to use RAII based on your own feelings on the situation though - it's a wonderful idea to use it everywhere, but some times when converting old code it can be a massive amount of work to fix all the call-chains up to use it.
One more thing - I'm not overly familiar with the GUI logic you're working with, so I won't go there specifically... but you'll have to look into how your resources should be copied and how long they should be maintained. Will your RAII containers be reference counting, or will they have value (copy) semantics? Reference counting smart-pointers like shared_ptr may solve your problem about recreation of resources frequently as long as you can pass a reference to the original around your code.