我有这样一个泄漏代码:
void f() {
SomeClass *sc = new SomeClass;
...
if (...) {
g(sc); // g() takes ownership of memory pointed to by sc
}
...
sc->SomeMethod();
...
}
我想通过使用智能指针来消除泄漏,想到了以下解决方案:
void f() {
smart_ptr<SomeClass> sc(new SomeClass);
...
if (...) {
g(sc.release()); // ownership is taken
}
...
sc->SomeMethod(); // sc points to the allocated memory regardless of whether ownership was taken or not
...
} // the memory is freed if ownership was not taken
尝试使用std::unique_ptr和std::shared_ptr。std::unique_ptr在释放后指向空指针,std::shared_ptr根本没有release()。手动增加std::shared_ptr的引用计数器会有所帮助,但正如我正确理解的那样,也没有这样的能力。
除了原始指针之外,还考虑使用std::unique_ptr,使代码保持原样,并在每次将原始指针传递给获得所有权的函数时调用release(),但这是一个非常模糊的解决方案。
我想知道是否有一个智能指针从标准库,适合我的目标,或者也许有一个理想或常见的技巧如何做,在我的情况下,或我可能错过了什么?
4条答案
按热度按时间62lalag41#
您只需多写一点代码就可以保留一个本地的非所有者视图:
niknxzdl2#
我不明白
g
取得所有权是什么意思,因为g
退出后你仍然要使用指针,如果你总是想在g
后使用指针,那么传递一个原始指针给g
并在块的末尾释放指针会更有意义。如果你想让
g
拥有所有权,并且只想在你的指针还存在的时候调用SomeMethod
,那么就给g
传递一个原始指针,并让它返回一个原始指针。如果指针在g
中被释放,那么就返回nullptr
,并在SomeMethod
调用之前检查它。7gcisfzg3#
可以使用
shared_ptr
,效果相同,shared_ptr
没有release()
函数,但是有reset()
函数,我想这就是您要找的,但是要等到调用SomeClass::SomeMethod()
之后才能调用sc.reset()
。vcudknz34#
g() takes ownership of memory pointed to by sc
这会阻碍您的计划,因为
g()
拥有内存,所以允许在调用sc->SomeMethod()
之前释放内存,这将导致未定义的行为。一个简单而安全的解决方案可能是更改
g()
以接受shared_ptr
而不是原始指针,这样调用方可以共享所有权。为了保留现有的调用站点,您可以同时引入g()
的重载,该重载接受原始指针,从原始指针构造shared_ptr
,然后调用接受shared_ptr
的版本。一个更复杂的解决方案可能涉及要求内存的新所有者为您调用
SomeMethod
。(创建一个标志来跟踪内存是否为您所有。)因为该内存不再是您可以访问的。您所做的事情就像买了一辆车,将其送给某人,然后偷偷溜进去开车兜风。这是盗窃。您将车送人,所以它不再是你的。你把记忆给了别人,所以它不再是你的。最好的解决方案可能是在设计中后退一两步并重新评估。有时,重新组织代码以采用不同的方法会使这种情况消失,就像变魔术一样。特别是当
f()
的真实的主体又大又复杂时。(保持函数简单并专注于单个任务。)