我应该只需要担心新的并将它们与删除匹配吗? 我有一个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
not
delete(origin)
@Chance:它们是等效的。
删除源代码
是常见的样式,但其中任何一种功能都是正确的。因此……如果没有新的分配,我可能会对内存泄漏的担忧视而不见?如果你没有分配内存,通常你也不需要取消分配它。但是有一些特殊情况:一些函数是e为您分配数据,希望您取消分配数据。但这种做法非常罕见,必须在适当的文档中正确描述。@Tryer:理想情况下,是的。除非您使用的底层程序的程序员经常出错。但是