Featured image of post Effective C++ 03 - 资源管理

Effective C++ 03 - 资源管理

小心对待一切资源

# Use object to manage resources

  1. 获得资源后立刻放入管理对象
  2. 管理对象运用析构函数确保资源被释放
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
void f() {
    Investment* pInv = createInvestment();
    // other operations

    // 可能因为一系列原因导致delete无法执行
    delete pInv; // release pointer
}

// manage resource by auto_ptr
void f2() {
    std::auto_ptr<Investment> pInv(createInvestment());
    // auto_ptr will automatically deconstruct and delete pInv
}

由于auto_ptr销毁时会自动删除所指之物,所以一定不能让多个auto_ptr指向同一对象。

若通过复制构造函数或复制操作符复制auto_ptr,它们会变成 null,而复制所得的指针将取得资源的唯一拥有权

1
2
3
std::auto_ptr<Investment> pInv1(createInvestment());
std::auto_ptr<Investment> pInv2(pInv1); // pInv1 becomes null
pInv1 = pInv2; // pInv2 becomes null

auto_ptr的替代方案是"引用计数型智慧指针"

1
2
3
4
5
void f() {
    std::tr1::shared_ptr<Investment> pInv1(createInvestment());
    std::tr1::shared_ptr<Investment> pInv2(pInv1);
    pInv1 = pInv2;
}

auto_ptr & tr1::shared_ptr两者都在其析构函数中做delete而不是delete[]操作。

# Think carefully about copying behavior in resource-managing classes

  1. 禁止复制
  2. 对底层资源使用"引用计数法" shared_ptr
  3. 复制底部资源
  4. 转移底部资源的拥有权 auto_ptr

# Provide access to raw resources in resource-managing classes

1
2
3
int daysHeld(const Investment *pi);

int days = daysHeld(pInv.get()); // return raw resource

提供显式转换函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
FontHandle getFont();
void releaseFont(FontHandle fh);

class Font {
public:
    explicit Font(FontHandle fh) : f(fh) {
    }
    ~Font() {
        releaseFont(f);
    }
private:
    FontHandle f;
}

提供隐式转换函数

1
2
3
4
5
6
7
8
class Font {
public:
    operator FontHandle() const {
        return f;
    }
private:
    FontHandle f;
}

# Use the same form in corresponding uses of new and delete

1
2
3
4
5
std::string* stringPtr1 = new std::string;
std::string* stringPtr2 = new std::string[100];

delete stringPtr1;
delete [] stringPtr2;

# Store new objects in smart pointer in standalone statements

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
int priority();
void processWidget(std::tr1::shared_ptr<Widget> pw, int priority);

processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority());
// 1. 执行 "new Widget"
// 2. 调用 priority => 如果抛出异常,new Widget返回的指针将会遗失
// 3. 调用 tr1::shared_ptr 构造函数

std::tr1::shared_ptr<Widget> pw(new Widget);
processWidget(pw, priority());
The older I get, the more I realize that most of life is a matter of what we pay attention to, of what we attend to [with focus].
Built with Hugo
Theme Stack designed by Jimmy