请假设我有一个接受指针作为参数的函数。此函数可以抛出异常,因为它用于std::vector<>::push_back()
管理此指针的生命周期。如果我这样声明:
void manage(T *ptr);
并这样称呼它:
manage(new T());
如果它抛出一个将指针推入的异常std::vector<>
,我实际上有内存泄漏,不是吗?
会像这样声明函数:
void manage(std::auto_ptr<T> ptr);
解决我的问题?
我希望它首先std::auto_ptr
在堆栈上分配 (我猜这永远不会引发异常)并让它获得对指针的所有权。安全的。
然后,在函数内部,我会将原始指针推入std::vector<>
,这也是安全的:如果失败,则不会添加指针,但智能指针仍将拥有指针,因此它将被销毁。如果推送成功,我将删除智能指针对该指针的所有权并返回:这不会引发异常,所以它总是没问题的。
我的理论正确吗?
- 编辑 -
不,我想我不能那样做。这样做需要对右值进行非常量引用(从智能指针中夺走所有权)。我必须写
std::auto_ptr<T> ptr(new T());
manage(ptr);
为此,在我的情况下,这很不方便。我写这个是为了在不污染代码的情况下实现 RAII。那么,做那件事也无济于事。那将是第 22 条渔获物。
-- 编辑 2 --
将 Jason Orendorff 所说的内容拉下来供读者快速参考,最终的解决方案似乎如下:
void manage(T *ptr)
{
std::auto_ptr<T> autoPtr(ptr);
vector.push_back(ptr);
autoPtr.release();
}
这解决了无用的非常量引用右值的问题。
当我完成这门课时,我正在编码,我会把它发回这里,以防有人发现它有用。
-- 编辑 3 --
好的,这里已经讨论了很多,还有一些我之前应该澄清的关键点。一般来说,当我在 stackoverflow 上发帖时,我会尝试解释我的问题背后的原因,一般来说,这是完全没用的。所以这次我想我应该直奔主题。结果发现效果不太好XD
不幸的是,我的大脑现在陷入僵局,所以我想我什至无法正确解释我最初想到的是什么来实现我的目标。我正在尝试为原子操作和异常安全的代码编写找到适合许多情况的良好解决方案,但实际上,我无法处理它 XD 我认为这是我只会随着时间的推移才能掌握的东西。
我是一个非常新的 C++ 程序员,我的重点是游戏开发。当游戏引擎中抛出异常时,就是执行的结束。系统将为我的进程释放所有内存,因此是否有一个或两个指针在这里和那里泄漏并不重要。现在我正在开发一个服务器应用程序,我发现处理异常很困难,因为异常不能使服务器崩溃;它必须“使请求崩溃”。
即“嗯,客户端,可惜开发者没有预见到这种情况,所以你以后得试试(到这里,基本上和游戏引擎一样,什么都没有修复,只是它与请求的上下文隔离,而不是整个过程。但是不要惊慌,因为一切都处于有效状态(但是,这是其中一个区别。过程没有终止,所以操作系统不能为你释放资源,而且你要注意撤消到目前为止的操作,这样你就不会完全锁定一个用户的帐户,甚至是服务器提供的全部服务)。”。
我只会越来越多地编写代码并记下我的问题,以便下次我可以写出更好的问题。我现在不准备问这个,我真的很抱歉。
非常感谢您的回复,我真的很喜欢stackoverflow。令人惊讶的是,我的问题得到了如此快速的回答,而您的回答又如此有启发性。谢谢。