You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++中从vector删除shared_ptr持有的资源并按需重新引入

问题描述

我需要从vector中删除/销毁网络资源,必要时重新引入。为此写了测试程序,但在删除shared_ptr并置为nullptr时遇到问题:直接置为nullptr会导致悬空指针,怎么在不内存泄漏的情况下释放该位置?

测试代码:

#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class ptr{
  public:
  int x;
  ptr(int a):x(a){  }
  ~ptr()
  {
       cout << "destructor\n";
  }
};
int main()
{
    std::vector<shared_ptr<ptr>>v;
    v.push_back(shared_ptr<ptr>(new ptr(100)));
    v.push_back(shared_ptr<ptr>(new ptr(200)));
    v.push_back(shared_ptr<ptr>(new ptr(300)));
    v.push_back(shared_ptr<ptr>(new ptr(400)));
    v.push_back(shared_ptr<ptr>(new ptr(500)));
    auto it = v.begin();
    int i = 0;
    while(i < 5)
    {
        if((*it)->x == 300)
        {
            cout << "300 found \n";
            delete (*it);  // -> Problem is here.
        }
        it++;
        i++;
    }
    return 0;
}
解决方案

你的核心问题是手动调用delete操作shared_ptr管理的对象,这完全违背了智能指针的设计初衷——shared_ptr会自动管理对象的生命周期,手动delete会导致重复释放,触发未定义行为。

正确的处理方式分两种场景:

场景1:彻底从vector中移除该元素

如果你不需要保留vector中的这个位置,直接用vector::erase删除迭代器指向的元素即可。erase会销毁这个shared_ptr,当shared_ptr的引用计数降为0时,自动调用对象的析构函数释放资源:

auto it = v.begin();
while (it != v.end()) {
    if ((*it)->x == 300) {
        cout << "300 found \n";
        // 移除元素,同时shared_ptr销毁,自动释放对象
        it = v.erase(it);
    } else {
        ++it;
    }
}

场景2:保留vector中的位置,仅释放资源(置为nullptr)

如果需要保留vector的size,只是把该位置的资源释放,直接将shared_ptr赋值为nullptr即可。shared_ptr被置空时,引用计数减1,若计数为0则自动销毁对象,不会产生悬空指针:

auto it = v.begin();
int i = 0;
while(i < 5)
{
    if((*it)->x == 300)
    {
        cout << "300 found \n";
        // 直接置空,shared_ptr自动管理资源释放
        *it = nullptr;
    }
    it++;
    i++;
}

问题根源解析

你手动delete (*it),相当于绕过shared_ptr直接释放了它管理的内存。但shared_ptr本身还持有这块内存的地址,当shared_ptr后续被销毁(比如vector析构时),会再次尝试释放这块已经被释放的内存,导致双重释放错误,这就是你遇到问题的核心原因。

内容的提问来源于stack exchange,提问作者Rasmi Ranjan Nayak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 00:06:00