我有一个C ++代码,其中我有多种数据类型。重要的是,我有一个班级:
class coordinate{
int x, y;
public:
void set_values(int, int);
}
然后我可能会说:
coordinate* origin = new coordinate;
显然,要恢复分配给原点的内存,我最后会说:
delete(origin);
到目前为止,非常好......
我的问题是,还有其他任何数据类型的删除/破坏我必须手动完全防止内存泄漏吗?
有问题的其他数据类型是:
string(此数据类型的对象似乎有一个end()函数),stringstream,char []。
例如。我有一个函数setname()从main()重复调用,执行此操作:
void setname(){
for(int k = 0; k < 10; k++){
string NAME = "Point ";
stringstream s;
s << k;
NAME += s.str();
char name[7];
strcpy(name,NAME.c_str());
/* some other stuff... */
NAME.end(); //<--------------is stuff like this really needed?
//will memory held by NAME, s and name be automatically released as k increments?
}
}
答案 0 :(得分:4)
每个new
应该与delete
匹配,每new []
到delete []
,每malloc
到free
(但不要在C ++中使用它们......)
答案 1 :(得分:3)
问题的解决方案是RAII。
这个想法是将资源绑定到堆栈上对象的生命周期。热门示例包括smart pointers,locks和file handles。
答案 2 :(得分:2)
作为一般规则:如果您new
,delete
它。如果你new[]
它,delete[]
它。如果你malloc()
,free()
它。
否则,通常不必做任何事情。 (Windows上的GlobalAlloc()
或Mac OS X / iOS上的CFStringCreate()
等特定于系统的内容有自己的规则。有关这些系统特定API的信息,请参阅手册/ FAQ / MSDN。)
答案 3 :(得分:1)
答案是:这取决于。如果您的代码使用string
分配任何内容(coordinate
,stringstream
类的实例,new
等),则某些代码(可能是您的代码)应{{1}它。否则,如果在堆栈上创建一个字符串并使用复制构造函数传递它,则不必删除它。
并且:根本不需要delete
。函数NAME.end()
实际上返回一个迭代器,指向字符串的末尾;它没有做任何清理。因此,在您的代码中,不需要调用end()
。
答案 4 :(得分:0)
您随时可以调查boost::shared_ptr。您仍然需要执行'new',但删除操作由共享ptr在内部处理。
答案 5 :(得分:0)
使用C ++ 0x / TR1 shared_ptr&lt;&gt;如果可以的话,它们绝对令人惊讶,有些人会说性能影响,但是,只有在探查器抱怨shared_ptr时才考虑其他选择。共享指针是线程安全的,并且在重新分配时具有非常好的行为(shared_ptr&lt;&gt; :: reset将拆分引用)。
你唯一需要注意的是new vs new [],这就是为什么我喜欢c类型内存分配器(calloc,malloc,free),如果我不需要构造函数和析构函数(即POD类型) )。
对于c类型分配器,您可以使用:shared_ptr<char> charptr((char*)calloc(10, sizof(char)), free);
P.S。:对于其他对象,请注意内核句柄和GDI对象(至少在Windows上),它们不会在传统意义上完全泄漏内存,但必须关闭。
此外,c类型函数通常会返回malloc'd指针。
答案 6 :(得分:0)
不,不,不。你使用RAII - 它是异常安全的。
基本上,当自定义类型的对象超出C ++范围时,它会调用一个特殊函数(称为析构函数)。这用于清理所有资源。它会自动应用,实际上,在您的程序可以合理地继续的所有场景中调用,以及一些它不能的场景。
这意味着你永远不必释放由自定义类型创建的内存 - 它应该自由释放。您不必释放由std :: string分配的内存,也不必释放std :: stringstream。 std :: string :: end()是关于结束迭代的。通常,对于需要自定义释放的任何资源,您将以自定义类型包装它们,以便它们不再需要手动释放。
对于使用new分配的自定义类型,您可以使用auto_ptr,当它超出范围并立即释放内存时会立即销毁该对象,或者您可以使用shared_ptr,它在指向它的所有实例之间“共享”对象通过一些魔法。还有其他类型的智能指针,对于任何给定的资源,您可以编写自己的自定义管理类型。这大大提高了程序的安全性,不会造成性能损失。
此外,您永远不应该使用char *或任何相关类型(char []等)来在C ++中存储字符串。使用std :: string。您当前的代码是不可维护的,因为如果您需要超过7个字符,它将会死亡或可能导致随机错误。 C风格的字符串函数(strcpy)同样被大大弃用,不应该使用。
(当然,每条规则都有例外,但C风格的字符串,你必须非常先进才能正确利用它们的优点。)
一般规则是,如果你曾经调用过一个在析构函数之外释放资源的函数,你几乎肯定写错了你的程序。