我应该只需要担心新的并将它们与删除匹配吗? 我有一个C++代码,其中有多个数据类型。重要的是,我有一门课: class coordinate{ int x, y; public: void set_values(int, int); }
那么我可以说:我应该只需要担心新的并将它们与删除匹配吗? 我有一个C++代码,其中有多个数据类型。重要的是,我有一门课: class coordinate{ int x, y; public: void set_values(int, int); },c++,memory-management,memory-leaks,C++,Memory Management,Memory Leaks,那么我可以说: coordinate* origin = new coordinate; 显然,要恢复分配给origin的内存,我最后会说: delete(origin); 到目前为止,一切都很好 我的问题是,是否有任何其他数据类型的删除/销毁我必须绝对手动处理,以防止内存泄漏 其他有问题的数据类型包括: string(此数据类型的对象似乎有一个end()函数)、stringstream、char[] 例如,我有一个函数setname(),它会从main()反复调用,这样做: void se
coordinate* origin = new coordinate;
显然,要恢复分配给origin的内存,我最后会说:
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?
}
}
void setname(){
对于(int k=0;k<10;k++){
string NAME=“点”;
细绳;
你的问题的解决办法是
有一个想法,就是将资源绑定到堆栈上对象的生命周期。流行的例子是,和.< /p> < p> <新的< /C> >应该匹配<代码>删除>代码>,每个<代码>新[]代码>代码> >代码>删除[]/Cord>,并且每个<代码> Malc > <代码>免费< /C>(但不要在C++中使用它们)
答案是:这取决于您的代码。如果您的代码使用新的分配了任何内容(一个字符串
、一个坐标
类的实例、一个字符串流
等),则一些代码(可能是您的代码)应该删除它。否则,如果您在堆栈上创建一个字符串并使用复制构造函数传递它,您就不必删除它
并且:NAME.end()
根本不需要。函数end()
实际上返回一个迭代器,指向字符串的末尾;它不进行任何清理。因此在代码中调用end()
是不需要的。一般来说:如果你新建它,删除它。如果你新建[]
它,删除[]
它。如果你malloc()
它,免费()
它
否则,您通常不必做任何事情。(Windows上的系统特定功能,如GlobalAlloc()
,或Mac OS X/iOS上的CFStringCreate()
,都有自己的规则。有关这些系统特定API的信息,请参阅手册/FAQ/MSDN。)您可以随时调查。您仍然需要执行“新建”,但删除是由共享ptr在内部处理的。如果可以,使用C++0x/TR1共享ptr,它们绝对令人惊讶,有人说会影响性能,但仍然只有在探查器抱怨共享ptr时才考虑其他替代方法。共享指针是线程安全,在重新分配时具有非常好的行为(shared_ptr::reset将分割引用)
你唯一应该注意的是new vs new[],这就是为什么我更喜欢c类型的内存分配器(calloc、malloc、free),如果我不需要构造函数和析构函数(即POD类型)
对于c类型分配器,您可以使用:shared\u ptr charptr((char*)calloc(10,sizof(char)),free);
注意:对于其他对象,请注意内核句柄和GDI对象(至少在windows上),它们并不是典型意义上的内存泄漏,而是必须关闭
此外,c类型函数通常返回malloc'd指针。不,不,不。您可以使用RAII来实现这一点——它是异常安全的
基本上,当一个自定义类型的对象在C++中超出范围时,它调用一个特殊的函数(称为析构函数)。它用来清理所有的资源。它被自动应用,在现实中,在所有的程序中都可以调用,程序可以合理地继续,而一些则不能。
这意味着您永远不必释放由自定义类型创建的内存-它应该释放自己。您不必释放由std::string或std::stringstream.std::string::end()分配的内存是关于结束迭代的。通常,对于需要自定义释放的任何资源,您将使用自定义类型对其进行包装,以便它们不再需要手动释放
对于使用new分配的自定义类型,您可以使用auto_ptr,当对象超出范围并释放内存时,它会立即销毁该对象,也可以使用shared_ptr,它“共享”通过某种魔力指向它的所有实例之间的对象。还有其他类型的智能指针,对于任何给定的资源,您都可以编写自己的自定义管理类型。这大大提高了程序的安全性,不会造成性能损失
也可以,你永远不应该使用Car *或任何相关类型(Car []等)来存储C++中的字符串。使用STD::String。当前代码不可维护,因为它会死掉,或者如果需要超过7个字符,可能会导致随机错误。C样式字符串函数(StrcPy)同样被非常不推荐使用,不应该使用。
(当然,每个规则都有例外,但是C风格的字符串,您必须非常先进才能正确地利用它们的优点)
一般的规则是,如果你调用一个函数将资源释放到析构函数之外,你几乎肯定写错了程序。std::string::end()
是STL迭代机制的一部分。它与内存管理无关。:)你想查一下什么std::string::end()
does?确保键入delete origin
notdelete(origin)
@Chance:它们是等效的。删除源代码
是常见的样式,但其中任何一种功能都是正确的。因此……如果没有新的分配,我可能会对内存泄漏的担忧视而不见?如果你没有分配内存,通常你也不需要取消分配它。但是有一些特殊情况:一些函数是e为您分配数据,希望您取消分配数据。但这种做法非常罕见,必须在适当的文档中正确描述。@Tryer:理想情况下,是的。除非您使用的底层程序的程序员经常出错。但是