当构造函数引发异常时,RAII如何工作?

编程入门 行业动态 更新时间:2024-10-25 22:29:16
本文介绍了当构造函数引发异常时,RAII如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我正在学习C ++中的RAII成语,以及如何使用智能指针。

在我的阅读中,我遇到了两件事,对我来说,似乎相互矛盾。

引自 http:/ /www.hackcraft/raii/ :

...如果已经创建了具有RAII语义的成员对象,在构造函数完成之前发生异常,那么它的析构函数将被调用作为堆栈展开的一部分。因此,控制多个资源的对象即使没有使用成员RAII对象完全构造,也可以对其进行清理。

但引用自 www.parashift/c++-faq-lite/exceptions.html#faq-17.10 :

如果构造函数抛出异常,则不会运行该对象的析构函数。如果您的对象已经完成了需要撤消的内容(例如分配一些内存,打开文件或锁定信号量),则该需要撤消的内容必须由对象中的数据成员记住。

然后,第二个链接的源建议使用智能指针来处理在构造函数中已经分配的事情的问题。 p>

那么在这些情况下实际发生了什么?

解决方案

你误会了第一个报价如果已经创建了具有RAII语义的成员对象,并且在构造函数完成之前发生异常,那么这并不困难,因为它是令人困惑的。

它的析构函数将被称为堆栈展开的一部分。

这就是说。如果已经创建了具有RAII语义的成员对象,并且发生异常,则 :

在外部对象的构造函数已经完成之前,外部对象中,成员对象的析构函数将作为堆栈展开的一部分被调用。

看到区别?这个想法是成员对象完成了它的构造函数,但是拥有类型没有。它在其构造函数(或另一个成员的构造函数)中的某处被初始化。这将导致所有成员的析构函数被调用(所有已完成构造的构造函数),而不是其自己的析构函数。

这是一个例子:

class SomeType { InnerType val; public: SomeType():val(...) { throw异常; } };

当您创建一个 SomeType 实例时,将调用 InnerType :: InnerType 。只要不抛出,它将进入 SomeType 的构造函数。当这种情况发生时,会导致 val 被破坏,从而调用 InnerType ::〜InnerType 。

I am learning about the RAII idiom in C++, and how to use smart pointers.

In my reading, I have come across two things that, to me, seem to contradict each other.

Quoted from www.hackcraft/raii/:

...if a member object with RAII semantics has been created and an exception happens before the constructor has completed then its destructor will be called as part of the stack unwinding. Hence an object which controls multiple resources can guarnatee their cleanup even if it isn’t fully constructed by using member RAII objects.

But quoted from www.parashift/c++-faq-lite/exceptions.html#faq-17.10:

If a constructor throws an exception, the object's destructor is not run. If your object has already done something that needs to be undone (such as allocating some memory, opening a file, or locking a semaphore), this "stuff that needs to be undone" must be remembered by a data member inside the object.

And then the second linked source recommends using smart pointers to deal with the issue of things that were already allocated in the constructor.

So what actually happens in these scenarios?

解决方案

You're misunderstanding the first quote. That's not hard, since it's confusing.

if a member object with RAII semantics has been created and an exception happens before the constructor has completed then its destructor will be called as part of the stack unwinding.

That's what it says. Here's what it meant:

if a member object with RAII semantics has been created and an exception happens in the outer object before the outer object's constructor has completed then the member object's destructor will be called as part of the stack unwinding.

See the difference? The idea is that the member object completed its constructor, but the owning type didn't. It threw somewhere in its constructor (or a constructor of another member that is initialized after that one). This will cause the destructor of all of its members to be called (all of the ones that completed construction, that is), but not its own destructor.

Here's an example:

class SomeType { InnerType val; public: SomeType() : val(...) { throw Exception; } };

When you create a SomeType instance, it will call InnerType::InnerType. As long as that doesn't throw, it will then enter SomeType's constructor. When that throws, it will cause val to be destroyed, thus calling InnerType::~InnerType.

更多推荐

当构造函数引发异常时,RAII如何工作?

本文发布于:2023-10-31 05:11:28,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1545102.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:函数   异常   工作   RAII

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!