class A
{
public:
A(){}
~A(){}
void DoSomething(int x){}
};
void func(int i)
{
A *pa = new A();
pa->DoSomething(i);
delete pa;
}
Run Code Online (Sandbox Code Playgroud)
你们看到这个代码有什么问题吗?我只能看到以下两点:
还有其他想法吗?
A应该在堆栈而不是堆上创建类的对象.
是的,pa应该创建为自动变量(在堆栈上)而不是动态(在堆上).
但是,写入也是错误的,因为它不是例外安全的.如果pa->DoSomething(i)抛出异常,您将泄漏指向的对象pa.
管理资源生命周期的正确方法是使用范围限制资源管理(SBRM;也称为资源获取是初始化).管理动态分配对象的RAII方法是使用智能指针:
void func(int i)
{
std::auto_ptr<A> pa(new A());
pa->DoSomething(i);
}
Run Code Online (Sandbox Code Playgroud)
手动资源管理是脆弱和危险的,因为它很容易出错.在这个简单的例子中,很容易看出pa->DoSomething(i)它不会抛出异常,因为它根本不做任何事情.但在几乎每一个真正的计划中,都不是那么容易.
随着程序规模和复杂性的增加,手动资源管理很快变得非常困难.使用Scope-Bound Resource Management进行自动资源管理可以很好地扩展.
func只对类的对象进行操作,A并且应该成为A.
这是不正确的.如果需要访问对象的内部状态,则只应将函数实现为成员函数.这意味着您应该尽可能将函数实现为非成员函数.
您拥有的成员函数越多,完全测试类所需的工作就越多,因为有更多方法可以修改类的内部状态.
Herb Sutter通过std::string在他的"周刊大师"一文"Monoliths Unstrung"中分解课程来解释这一原则.