C++指针重复删除问题:如何让Canvas类释放指针所有权(不修改main)
问题根源
你的代码中,Canvas::Add方法将传入的原始指针包装成std::unique_ptr,把指针的所有权转移给了Canvas类。当m_canvasItems中的unique_ptr被销毁(比如Canvas对象析构、vector元素被清除)时,会自动调用delete释放指针。而main函数中又手动调用delete,导致同一指针被两次释放,触发内存错误。
可行方案
由于无法修改main.cpp的逻辑,你需要让Canvas类只保存指针的引用,不获取所有权。有两种合理的实现方式:
方案1:修改Canvas的存储类型(推荐)
将m_canvasItems的类型从std::vector<std::unique_ptr<CanvasItem>>改为std::vector<CanvasItem*>,让Canvas仅保存原始指针,不管理其生命周期:
// Canvas类的成员变量修改 std::vector<CanvasItem*> m_canvasItems; // 修改Add方法 void Canvas::Add(CanvasItem* item) { m_canvasItems.push_back(item); // 仅存储指针,不转移所有权 }
同时确保Canvas的析构函数不会删除这些指针(默认析构函数就不会,无需额外操作)。这样main函数中手动delete指针时,不会和Canvas的操作冲突。
方案2:利用std::unique_ptr::release(仅当无法修改存储类型时使用)
如果因为代码依赖无法修改m_canvasItems的类型,你可以在Add方法中创建unique_ptr后立刻调用release(),放弃对指针的所有权:
void Canvas::Add(CanvasItem* item) { std::unique_ptr<CanvasItem> ptr(item); m_canvasItems.push_back(std::move(ptr)); // 释放所有权,让unique_ptr不再管理该指针 m_canvasItems.back().release(); }
注意:这种方式下,m_canvasItems中的unique_ptr会变成空指针,如果你需要通过Canvas访问这些CanvasItem对象,还需要额外存储原始指针(比如再维护一个vector<CanvasItem*>),因此方案1是更简洁的选择。
关键说明
std::unique_ptr::release的作用正是释放智能指针对原始指针的所有权,返回原始指针且不触发删除操作,完全符合你需要让main接管所有权的需求。但只有在无法修改存储类型的场景下,才推荐用这种方式。
内容的提问来源于stack exchange,提问作者Toseef_Ahmed

