C++伪代码中是否需用new关键字?内存释放时机咨询
问题
代码片段
while(!fileEnd) { rectD *rD = new rectD(); symbol *sb = new symbol(rD); while( true ) { if(closing brace) { sb->rD->isSymbol = true; sb->shapes[currentSymName] = *(sb->rD); // shapes is a std::map allSymbol[currentSymName] = sb; // allSymbol is a std::map break; } else { if(condition 1) sb->fun1(); if(condition 2) sb->fun2(); } } }
疑问
后续程序中会使用shapes和allSymbol这两个std::map。想咨询:上述代码中是否有必要使用new关键字?
已知使用new创建的对象位于堆内存,不使用new则对象位于栈内存;堆内存需手动delete释放,栈内存会在函数作用域结束时自动释放。
虽然当前函数作用域结束后不再直接使用*rD和*sb,但整个程序运行期间都会用到包含*rD和*sb的shapes与allSymbol。因此困惑是否该使用new关键字,若必须使用,应在何处delete以避免内存泄漏?
回答
是否需要用new?
必须用。原因很明确:
- 栈对象的生命周期仅限于当前循环迭代,每次循环结束栈上的
sb和rD都会被销毁。但你需要sb存活到整个程序运行期(因为allSymbol存了它的指针),如果不用new,allSymbol里的指针会变成野指针,访问时直接触发未定义行为。 - 对于
rD,虽然shapes里存的是它的副本,但循环过程中sb的fun1()、fun2()可能还会操作这个rD,如果是栈对象,迭代结束后就失效了,sb内部的指针会指向垃圾内存。
手动管理内存的释放点
如果坚持用裸指针,得在程序彻底不需要allSymbol和相关对象时手动释放:
- 遍历
allSymbol的每个symbol*指针,执行delete操作。注意要给symbol写正确的析构函数——如果symbol拥有rD的所有权,析构函数里要delete rD,不然rD的内存会泄漏;如果rD的所有权不属于symbol,那还要单独遍历释放所有rD(但从代码逻辑看,rD是和sb绑定创建的,应该让symbol负责清理rD)。 shapes里存的是rectD的副本,std::map会自动管理这些对象的内存,不需要额外处理。
更省心的方案:用智能指针
别折腾裸指针了,直接用C++11的智能指针:
- 把
allSymbol的类型改成std::map<Key, std::unique_ptr<symbol>>(独占所有权)或者std::map<Key, std::shared_ptr<symbol>>(共享所有权),根据你的实际需求选。 - 创建对象时用
std::make_unique<symbol>(rD)或者std::make_shared<symbol>(rD),智能指针会在对象没人用的时候自动调用delete,完全不用手动管释放,从根源避免内存泄漏。 - 连
rD也可以改成让symbol内部存std::unique_ptr<rectD>,彻底把内存管理交给标准库,减少出错概率。
内容的提问来源于stack exchange,提问作者tushar
相关产品推荐
相关产品推荐

