对于小程序,我们可以通过这种方式防止内存泄漏:
proc() {
//allocate memory for matrix
try {
}
catch {
//free matrix memory
}
...
//free matrix memory
}
如果我们的程序更复杂:
proc() {
//allocate memory for matrix
try {
}
catch {
//free matrix memory
}
...
try {
}
catch {
//free matrix memory
}
...
try {
}
catch {
//free matrix memory
}
...
//free matrix memory
}
看起来有点笨拙。 是一种更好的方法,更好的编程风格是否存在内存泄漏控制? 据我所知,C ++有auto_ptr,我们可以开发程序而不需要关心内存释放。
proc() {
//allocate auto_ptr
try {
}
catch {
}
...
}
但据我所知,auto_ptr甚至不适用于数组。因此,在一般情况下,这是不可接受的方式。
答案 0 :(得分:13)
auto_ptr
不是一个独特的案例。这不是“auto_ptr
或没有”。 auto_ptr
是一般编程习惯用法的一个例子,它处理资源分配/解除分配而没有泄漏。
这个习语称为RAII。
这意味着资源应该映射到一个对象,该对象管理资源的生命周期,并确保在适当的时候清理它。
在auto_ptr
的情况下,这只需要通过让类存储指向已分配内存的指针来完成,并且在该类的析构函数中,在指针上调用delete
。
您可以使用自己的RAII课程而不是auto_ptr
执行相同操作。
但是还有其他类型的智能指针,它们优于auto_ptr
(事实上,在C ++ 11中已被弃用)。
它们是shared_ptr
(引用计数的智能指针,在最后一个引用存在时删除对象),scoped_ptr
(更安全但有限,相当于auto_ptr
可以在C ++ 03)和unique_ptr
中实现,auto_ptr
是auto_ptr
的C ++ 11替代,它解决了unique_ptr
所遇到的问题。 auto_ptr
可以安全地用在数组和标准容器中。
所以你不应该使用{{1}},但你绝对应该使用其他类型的智能指针和RAII。
答案 1 :(得分:8)
根本不要在客户端代码中使用手动内存分配!
相反,设计一个负责自己业务的Matrix
类。然后你可以说,
void proc()
{
Matrix m1; // might throw
// ...
Matrix m2; // might also throw
// ...
}
即使在任何地方的任何异常中,所有已经存在的对象都会被销毁,如果你设计了正确的类,那么这将释放所有动态资源。
Matrix
类的非常婴儿的例子:
struct Matrix
{
Matrix(size_t m, size_t n) : buf(m * n), M(m), N(n) { }
int & operator(size_t i, size_t j) { return buf[i * N + j]; }
private:
std::vector<int> buf;
size_t M;
size_t N;
};
我实际上是懒惰并将所有实际动态数据降级为std::vector
;无需重新发明轮子! (或者只是使用Boost.MultiArray。)
答案 2 :(得分:3)
还有更多可用的智能指针,例如from Boost,其中一些已被纳入新的C ++标准。
但是,对于数组而言,“正确的选择”只是使用STL容器,特别是std::vector
如果您使用动态数组 - 在当前编译器上它具有与“常规”数组相同的性能
请记住,问题比内存更通用:必须获取和发布的每个资源都会产生同样的问题,C ++解决方案是使用类似智能指针的类来包装它们(获取构造函数中的所有权) ,破坏析构函数中的资源);这个成语通常称为RAII(资源获取是初始化)。
请注意,在带有异常的C ++代码中,这似乎是处理问题的唯一实用方法(因为该语言不提供finally
块或using
语句,并且每条指令都是由于异常导致的潜在回报路径。)
答案 3 :(得分:1)
你是对的,自动指针不是用于数组的方式,C风格的指针可以用来引用数组。这就是为什么还有其他容器,例如std::vector
,std::deque
等。您只需使用std::vector<std::shared_ptr<T> >
。