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

C++中类指针存入map的内存泄漏问题及智能指针解决方案

问题解答

1. 内存泄漏问题

这段代码会明确导致内存泄漏。你通过new手动分配了10个Person对象的堆内存,但全程没有调用delete释放这些内存。虽然程序退出后操作系统会回收进程占用的所有内存,但从C++标准和内存管理规范来说,这属于典型的内存泄漏场景——如果是长期运行的服务类程序,这类泄漏会持续消耗系统内存,最终引发性能问题甚至崩溃。

2. 用智能指针解决内存泄漏

使用C++标准库的智能指针可以自动管理内存,无需手动调用delete,推荐用std::unique_ptr(因为std::map是这些Person对象的唯一所有者,独占所有权更高效),也可以根据需求用std::shared_ptr(适用于多所有者场景)。

基于std::unique_ptr的实现

#include <iostream>
#include <map>
#include <memory>
#include <string>

class Person
{
private:
    int m_age;
    std::string m_name;

public:
    Person(int age, std::string name):
        m_age(age),
        m_name(std::move(name))  // 用move避免字符串拷贝,优化性能
    {}
    
    void PrintPerson() const  // 成员函数加const,符合const正确性
    {
        std::cout << "name: " << m_name << "\n";
        std::cout << "age: " << m_age << "\n";
    }
};

int main()
{
    // 用unique_ptr作为map的值类型
    std::map<size_t, std::unique_ptr<Person>> person_map;
    
    for (int n = 0; n < 10; ++n)
    {
        // 用make_unique创建unique_ptr,避免直接用new
        person_map.emplace(n, std::make_unique<Person>(n, std::to_string(n)));
    }
    
    for (const auto& pair : person_map)
    {
        pair.second->PrintPerson();
    }
    
    // 无需手动delete,map销毁时会自动释放所有unique_ptr管理的内存
    return 0;
}

补充:直接存储对象(更简单的方案)

如果Person类的拷贝/移动开销不大(比如示例中只有int和string,移动成本很低),直接在std::map中存储Person对象是更简洁的选择,完全不需要指针:

#include <iostream>
#include <map>
#include <string>

class Person
{
private:
    int m_age;
    std::string m_name;

public:
    Person(int age, std::string name):
        m_age(age),
        m_name(std::move(name))
    {}
    
    void PrintPerson() const
    {
        std::cout << "name: " << m_name << "\n";
        std::cout << "age: " << m_age << "\n";
    }
};

int main()
{
    std::map<size_t, Person> person_map;
    
    for (int n = 0; n < 10; ++n)
    {
        // emplace直接在map中构造对象,避免额外拷贝
        person_map.emplace(n, n, std::to_string(n));
    }
    
    for (const auto& pair : person_map)
    {
        pair.second.PrintPerson();
    }
    
    return 0;
}

3. 手动管理内存的正确方式(不推荐)

如果一定要用裸指针,必须在程序结束前手动遍历map并delete每个对象,同时要注意异常安全(比如如果delete前程序抛出异常,会跳过释放逻辑):

int main()
{
    std::map<size_t, Person*> person_map;
    
    for (int n = 0; n < 10; ++n)
    {
        person_map.insert(std::make_pair(n, new Person(n, std::to_string(n))));
    }
    
    for (int n = 0; n < 10; ++n)
    {
        person_map.at(n)->PrintPerson();
    }
    
    // 手动释放所有对象内存
    for (auto& pair : person_map)
    {
        delete pair.second;
    }
    
    return 0;
}

这种方式容易出错,因此强烈建议优先使用智能指针或直接存储对象的方案。


内容的提问来源于stack exchange,提问作者Nick X Tsui

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 21:33:23