资源获取是初始化“RAII”
在下面的示例中,
class X
{
int *r;
public:
X() {
cout << "X is created";
r = new int[10];
};
~X() {
cout<< "X is destroyed";
delete [] r;
};
};
class Y
{
public:
Y() {
X x;
throw 44;
};
~Y() {
cout << "Y is destroyed";
};
};
我从一个站点获取了 RAII 示例,并提出了一些疑问。请帮忙。
- 在 x 的构造函数中,我们没有考虑“如果内存分配失败”的场景。
- 这里 Y 的析构函数是安全的,因为 y 构造函数没有分配任何内存。如果我们还需要在 y 构造函数中进行一些内存分配怎么办?
in the example below
class X
{
int *r;
public:
X() {
cout << "X is created";
r = new int[10];
};
~X() {
cout<< "X is destroyed";
delete [] r;
};
};
class Y
{
public:
Y() {
X x;
throw 44;
};
~Y() {
cout << "Y is destroyed";
};
};
I got this example of RAII from one site and ave some doubts. please help.
- in the contructor of x we are not considering the scenation "if the memory allocation fails" .
- Here for the destructor of Y is safe as in y construcotr is not allocating any memory. what if we need to do some memory allocation also in y constructor?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在
X
的构造函数中,如果new
失败,则会抛出异常 (std::bad_alloc
)。这意味着构造函数永远不会完成,因此对象的生命周期永远不会开始,因此它的析构函数永远不会被调用(没有对象),并且new[]
和delete[]. (
X
应该有一个用户声明的复制构造函数和一个用户声明的复制赋值运算符,因为如果构造成功且对象被复制或赋值,提供的实现将打破此保证。)在
Y
,如果它在构造函数中分配内存并且分配成功,那么它需要确保在构造的其余部分在任何时候抛出异常并且构造函数完成内存被释放时释放该内存。在析构函数中释放(假设内存设计为持续对象的生命周期长度)。为了使这更容易,任何分配的内存都应该立即交给一个对象,该对象的唯一职责是释放内存。让一个类管理指向多个已分配内存块的原始指针是复杂且容易出错的管理代码的一个秘诀。
In the constructor of
X
, ifnew
fails it throws an exception (std::bad_alloc
). This means that the constructor never completes so the object's lifetime never starts so its destructor is never called (there is no object) and there is no mismatch betweennew[]
anddelete[]
. (X
should have a user-declared copy constructor and a user-declared copy assignment operator as the implementation provided ones would break this guarantee if construction succeeds and the object is copied or assigned.)In
Y
, if it allocates memory in it's constructor and this allocation is successful then it needs to ensure that this memory is freed if the rest of the construction throws an exception at any point and, if the constructor completes that the memory is freed in the destructor (assuming that the memory is designed to last the length of the lifetime of the object).To make this easier any allocated memory should be immediately handed to an object whose single responsibility is to free the memory. Having one class manage raw pointers to multiple blocks of allocated memory is a recipe for complicated and error-prone management code.
在 x 的构造函数中,我们不考虑“如果内存分配失败”的场景。
您不必这样做。如果失败,构造函数将抛出
std::bad_alloc
。即:new int[]
分配失败,抛出std::bad_alloc
。内存永远不会被分配。因此不存在泄漏。
这里 Y 的析构函数是安全的,因为 y 构造函数没有分配任何内存。如果我们还需要在 y 构造函数中进行一些内存分配怎么办?
你仍然没有问题。分配失败将抛出
std::bad_alloc
。这种失败是那些使用你的类的人的责任。new int[]
分配成功。delete[]
是new int[]
。同样,这里没有资源泄漏。
请注意,您确实需要警惕多次分配。即:
现在我们有资源泄漏。当构造函数抛出异常时,该对象永远不会完全构造。由于它从未完全构造,因此永远不会调用它的析构函数。因此我们泄漏了
r
。in the contructor of x we are not considering the scenation "if the memory allocation fails" .
You don't have to. If it fails, the constructor will throw
std::bad_alloc
. I.e.:new int[]
allocation fails, throwingstd::bad_alloc
. The memory is never allocated.Therefore there are no leaks.
Here for the destructor of Y is safe as in y construcotr is not allocating any memory. what if we need to do some memory allocation also in y constructor?
You still have no problem. Allocation failures will throw
std::bad_alloc
. That failure is the responsibility of those using your class.new int[]
allocation succeeds.delete[]
s thenew int[]
.Again, no resources are leaked here.
Note that you do need to be wary of multiple allocations. I.e.:
NOW we have a resource leak. When the exception is thrown from the constructor, the object is never fully constructed. Since it's never fully constructed, it's never going to have it's destructor called. Therefore we leak
r
.