0%

Use smart pointer to handle resources

真是後知後覺啊,最近才常是用這種方式。
先來用傳統的C語言分配資源寫法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
typedef struct B1 {
...
} B1;
typedef struct B2 {
...
} B2;
typedef struct D {
B1 *p1;
B2 *p2;
} D;
D* alloc_D()
{
D *obj = (D *)malloc(sizeof(D));
if (obj == NULL)
return NULL;
obj->p1 = (B1 *)malloc(sizeof(B1));
if (obj->p1 == NULL) {
free(obj);
return NULL;
}
obj->p2 = (B2 *)malloc(sizeof(B2));
if (obj->p2 == NULL) {
free(obj->p1);
free(obj);
return NULL;
}
return obj;
}
void free_D(D *obj)
{
if (obj) {
free(obj->p2);
free(obj->p1);
free(obj);
}
}

雖說用goto可以簡化alloc的情況,不過要不要用goto見仁見智。
如果是C++的話可以這樣寫

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct D {
B1 *p1;
B2 *p2;
D() {
try {
p1 = new B1;
p2 = new B2;
}
catch (...) {
delete p2;
delete p1;
}
}
~D()
{
delete p2;
delete p1;
}
};

在Constructor中可以接收Exception,保證Object要嘛無法使用,要嘛是一個完整的狀態。
這邊看到刪除的部份程式碼重複了,因此用Smart pointer可以更進一步。

1
2
3
4
5
6
struct D {
unique_ptr<B1> p1;
unique_ptr<B2> p2;
D() : p1(new B1), p2(new B2) {}
~D() = default;
};

Reference

Is it ever not safe to throw an exception in a constructor?
C++ : handle resources if constructors may throw exceptions