在 C++ 编程中,内存管理是核心知识点之一。标准库通过allocator提供了灵活的内存分配机制,而容器(如vector)则封装了内存管理细节。本文将通过实现一个简化版的allocator和vector,深入解析 C++ 内存管理的底层原理

一、内存管理基础:从原始内存到对象

C++ 中,内存管理涉及两个关键步骤:

  1. 内存分配 / 释放:通过operator new[]/operator delete[]操作原始内存块
  2. 对象构造 / 析构:通过placement new在已分配内存上构造对象,显式调用析构函数销毁对象

下面通过代码示例展示底层内存操作:

// 演示底层内存操作:分配原始内存->构造对象->销毁对象->释放内存
void demonstrateMemoryOperation() {
    cout << string(30, '=') << endl;
    cout << "演示底层内存操作" << endl;
    cout << string(30, '=') << endl;

    // 1. 分配原始内存(仅分配空间,不构造对象)
    cout << "使用operator new[]分配原始内存" << endl;
    void* raw_memory = operator new[](sizeof(int) * 5);  // 分配5个int的内存
    cout << "分配的内存地址:" << raw_memory << endl;

    // 2. 在指定内存位置构造对象(placement new)
    cout << "\n在指定位置构造对象(placement new)" << endl;
    int* int_array = static_cast<int*>(raw_memory);
    for (int i = 0; i < 5; i++) {
        // 在已分配的内存上构造int对象(不分配新内存)
        new(int_array + i) int(i * 10);  // placement new语法
        cout << "在地址" << (int_array + i) << "构造了值:" << i * 10 << endl;
    }

    // 3. 使用构造好的对象
    cout << "\n构造完成的数组内容:" << endl;
    for (int i = 0; i < 5; i++) {
        cout << int_array[i] << " ";
    }
    cout << endl;

    // 4. 释放内存(对于基础类型可直接释放,复杂类型需先析构)
    cout << "\n释放原始内存" << endl;
    operator delete[](int_array);  // 释放内存块
}

关键知识点

  • operator new[]仅分配内存,不调用构造函数
  • placement new语法:new(地址) 类型(参数),在指定地址构造对象
  • 基础类型可直接释放内存,自定义类型需先显式调用析构函数

二、自定义 Allocator:内存分配器

标准库std::allocator封装了内存管理逻辑,我们可以实现一个简化版来理解其原理:

// 自定义内存分配器:封装内存分配/释放和对象构造/析构
template<typename T>
class SimpleAllocator {
public:
    // 类型定义(遵循标准allocator接口规范)
    typedef T value_type;         // 分配的对象类型
    typedef T* pointer;           // 指向对象的指针
    typedef const T* const_pointer; // 指向常量对象的指针
    typedef T& reference;         // 对象的引用
    typedef const T& const_reference; // 常量对象的引用
    typedef size_t size_type;     // 大小类型
    typedef ptrdiff_t difference_type; // 指针差值类型

    // 1. 分配内存(仅分配,不构造对象)
    pointer allocate(size_type n) {
        cout << "分配" << n << "个" << typeid(T).name() << "类型的内存" << endl;
        // 分配n个T类型大小的内存块
        return static_cast<pointer>(operator new[](n * sizeof(T)));
    }

    // 2. 构造对象(在已分配内存上)
    void construct(pointer p, const_reference val) {
        cout << "在地址" << p << "构造对象" << endl;
        new(p) T(val);  // placement new:拷贝构造对象
    }

    // 3. 释放内存(仅释放,不析构对象)
    void deallocate(pointer p, size_type n) {
        cout << "释放" << n << "个对象的内存" << endl;
        operator delete[](p);  // 释放内存块
    }

    // 4. 析构对象(仅析构,不释放内存)
    void destroy(pointer p) {  
        cout << "在地址" << p << "析构对象" << endl;
        p->~T();  // 显式调用析构函数
    }
};

Allocator 设计要点

  • 分离内存分配(allocate)和对象构造(construct
  • 分离对象析构(destroy)和内存释放(deallocate
  • 遵循标准接口规范,便于与容器结合使用

三、自定义 Vector:SimpleVector 实现

基于上面的SimpleAllocator,我们实现一个简化版的vector,重点关注动态扩容机制:

// 自定义动态数组:基于SimpleAllocator实现
template<typename T>
class SimpleVector {
private:
    T* element;       // 指向数组起始位置
    T* first_free;    // 指向最后一个已构造对象的下一个位置
    T* end;           // 指向数组内存末尾(容量边界)
    SimpleAllocator<T> alloc;  // 内存分配器

    // 动态扩容核心函数
    void reAllocate() {
        cout << "\n---------开始扩容---------" << endl;
        size_t old_size = size();  // 当前元素数量
        // 计算新容量:空容器初始化为1,否则翻倍
        size_t new_capacity = old_size == 0 ? 1 : old_size * 2;
        cout << "当前大小: " << old_size << ",新容量: " << new_capacity << endl;

        // 1. 分配新内存
        T* new_element = alloc.allocate(new_capacity);

        // 2. 拷贝构造元素到新内存
        T* dest = new_element;  // 新内存的目标位置
        for (T* src = element; src != first_free; ++src, ++dest) {
            alloc.construct(dest, *src);  // 拷贝构造
        }

        // 3. 析构旧内存中的元素
        for (T* p = first_free; p != element; ) {
            alloc.destroy(--p);  // 从后往前析构
        }

        // 4. 释放旧内存
        if (element != nullptr) {
            alloc.deallocate(element, end - element);
        }

        // 5. 更新指针
        element = new_element;
        first_free = element + old_size;  // 保持元素数量不变
        end = element + new_capacity;     // 容量更新为新值

        cout << "---------扩容完成---------" << endl;
    }

public:
    // 构造函数:初始化空容器
    SimpleVector() : element(nullptr), first_free(nullptr), end(nullptr) {
        cout << "SimpleVector初始化完成(空容器)" << endl;
    }

    // 析构函数:释放所有资源
    ~SimpleVector() {
        // 1. 析构所有元素
        for (T* p = first_free; p != element; ) {
            alloc.destroy(--p);
        }
        // 2. 释放内存
        if (element != nullptr) {
            alloc.deallocate(element, end - element);
        }
    }

    // 向容器尾部添加元素
    void push_back(const T& t) {  // 原代码笔误pubsh_back->push_back
        cout << "\n添加元素: " << t << endl;
        // 若容量不足则扩容
        if (first_free == end) {
            reAllocate();
        }
        // 构造新元素并移动指针
        alloc.construct(first_free, t);
        ++first_free;
        cout << "添加完成。当前大小: " << size() 
             << ",容量: " << capacity() << endl;
    }

    // 获取当前元素数量
    size_t size() const {
        return first_free - element;
    }

    // 获取当前容量(可容纳的最大元素数)
    size_t capacity() const {
        return end - element;
    }

    // 重载[]运算符:访问元素
    T& operator[](size_t index) {
        return element[index];
    }
    const T& operator[](size_t index) const {
        return element[index];
    }

    // 打印容器内容
    void print() const {
        cout << "容器内容: [";
        for (const T* p = element; p != first_free; ++p) {
            if (p != element) cout << ",";
            cout << *p;
        }
        cout << "]" << endl;
        cout << "大小: " << size() << "; 容量: " << capacity() << endl;
    }
};

SimpleVector 核心机制

  1. 三指针管理element(起始)、first_free(已用边界)、end(容量边界)

  2. 动态扩容

    容量不足时翻倍(reAllocate函数),步骤为:

    • 分配更大内存块
    • 拷贝构造元素到新内存
    • 析构旧内存元素
    • 释放旧内存并更新指针
  3. 资源管理:析构函数确保所有元素被析构且内存被释放

四、测试与验证

为验证实现的正确性,我们使用基础类型(int)和自定义类型(TestClass)进行测试:

// 测试用自定义类:用于验证对象的构造/析构行为
class TestClass {
private:
    int value;
    string name;

public:
    // 构造函数
    TestClass(int v, const string& n) : value(v), name(n) {
        cout << "TestClass构造: " << name << "(" << value << ")" << endl;
    }

    // 拷贝构造函数
    TestClass(const TestClass& other) : value(other.value), name(other.name) {
        cout << "TestClass拷贝构造: " << name << "(" << value << ")" << endl;
    }

    // 析构函数
    ~TestClass() {
        cout << "TestClass析构: " << name << "(" << value << ")" << endl;
    }

    // 重载输出运算符:便于打印
    friend ostream& operator<<(ostream& os, const TestClass& obj) {
        os << obj.name << "(" << obj.value << ")";
        return os;
    }
};

// 主函数:测试所有功能
int main() {
    cout << string(60, '=') << endl;
    cout << "C++内存机制与Allocator演示" << endl;
    cout << string(60, '=') << endl;

    // 1. 演示底层内存操作
    demonstrateMemoryOperation();

    // 2. 测试int类型的SimpleVector
    cout << "\n" << string(60, '=') << endl;
    cout << "测试int类型的SimpleVector" << endl;
    cout << string(60, '=') << endl;
    SimpleVector<int> int_vec;
    for (int i = 0; i <= 8; i++) {  // 插入9个元素,触发多次扩容
        int_vec.push_back(i);
        int_vec.print();
    }

    // 3. 测试自定义类型的SimpleVector
    cout << "\n" << string(60, '=') << endl;
    cout << "测试TestClass类型的SimpleVector" << endl;
    cout << string(60, '=') << endl;
    SimpleVector<TestClass> class_vec;
    class_vec.push_back(TestClass(1, "obj1"));  // 临时对象->拷贝构造
    class_vec.push_back(TestClass(2, "obj2"));
    class_vec.push_back(TestClass(3, "obj3"));

    cout << "\n最终容器内容:" << endl;
    class_vec.print();

    cout << "\n" << string(60, '=') << endl;
    cout << "程序结束,开始析构..." << endl;
    cout << string(60, '=') << endl;
    return 0;
}

五、总结

通过实现SimpleAllocatorSimpleVector,深入理解了 C++ 内存管理的核心思想:

  1. 分离内存与对象:内存分配≠对象构造,内存释放≠对象析构
  2. 容器扩容机制:通过重新分配内存、拷贝元素、释放旧内存实现动态增长
  3. 资源安全:确保所有构造的对象都被正确析构,避免内存泄漏

标准库的std::allocatorstd::vector在此基础上做了更多优化(如移动语义、内存池等),但核心原理一致。掌握这些底层机制,能帮助更好地理解 C++ 容器的行为,写出更高效、更安全的代码。

完整代码

#include<iostream>
using namespace std;
#include<memory>
#include<new>
#include<algorithm>
#include<string>

// 自定义内存分配器:封装内存分配/释放和对象构造/析构
template<typename T>
class SimpleAllocator {
public:
    // 类型定义(遵循标准allocator接口规范)
    typedef T value_type;         // 分配的对象类型
    typedef T* pointer;           // 指向对象的指针
    typedef const T* const_pointer; // 指向常量对象的指针
    typedef T& reference;         // 对象的引用
    typedef const T& const_reference; // 常量对象的引用
    typedef size_t size_type;     // 大小类型
    typedef ptrdiff_t difference_type; // 指针差值类型

    // 1. 分配内存(仅分配,不构造对象)
    pointer allocate(size_type n) {
        cout << "分配" << n << "个" << typeid(T).name() << "类型的内存" << endl;
        // 分配n个T类型大小的内存块
        return static_cast<pointer>(operator new[](n * sizeof(T)));
    }

    // 2. 构造对象(在已分配内存上)
    void construct(pointer p, const_reference val) {
        cout << "在地址" << p << "构造对象" << endl;
        new(p) T(val);  // placement new:拷贝构造对象
    }

    // 3. 释放内存(仅释放,不析构对象)
    void deallocate(pointer p, size_type n) {
        cout << "释放" << n << "个对象的内存" << endl;
        operator delete[](p);  // 释放内存块
    }

    // 4. 析构对象(仅析构,不释放内存)
    void destroy(pointer p) {  // 注意:原代码笔误destory->destroy
        cout << "在地址" << p << "析构对象" << endl;
        p->~T();  // 显式调用析构函数
    }
};

// 自定义动态数组:基于SimpleAllocator实现
template<typename T>
class SimpleVector {
private:
    T* element;       // 指向数组起始位置
    T* first_free;    // 指向最后一个已构造对象的下一个位置
    T* end;           // 指向数组内存末尾(容量边界)
    SimpleAllocator<T> alloc;  // 内存分配器

    // 动态扩容核心函数
    void reAllocate() {
        cout << "\n---------开始扩容---------" << endl;
        size_t old_size = size();  // 当前元素数量
        // 计算新容量:空容器初始化为1,否则翻倍
        size_t new_capacity = old_size == 0 ? 1 : old_size * 2;
        cout << "当前大小: " << old_size << ",新容量: " << new_capacity << endl;

        // 1. 分配新内存
        T* new_element = alloc.allocate(new_capacity);

        // 2. 拷贝构造元素到新内存
        T* dest = new_element;  // 新内存的目标位置
        for (T* src = element; src != first_free; ++src, ++dest) {
            alloc.construct(dest, *src);  // 拷贝构造
        }

        // 3. 析构旧内存中的元素
        for (T* p = first_free; p != element; ) {
            alloc.destroy(--p);  // 从后往前析构
        }

        // 4. 释放旧内存
        if (element != nullptr) {
            alloc.deallocate(element, end - element);
        }

        // 5. 更新指针
        element = new_element;
        first_free = element + old_size;  // 保持元素数量不变
        end = element + new_capacity;     // 容量更新为新值

        cout << "---------扩容完成---------" << endl;
    }

public:
    // 构造函数:初始化空容器
    SimpleVector() : element(nullptr), first_free(nullptr), end(nullptr) {
        cout << "SimpleVector初始化完成(空容器)" << endl;
    }

    // 析构函数:释放所有资源
    ~SimpleVector() {
        // 1. 析构所有元素
        for (T* p = first_free; p != element; ) {
            alloc.destroy(--p);
        }
        // 2. 释放内存
        if (element != nullptr) {
            alloc.deallocate(element, end - element);
        }
    }

    // 向容器尾部添加元素
    void push_back(const T& t) {  // 原代码笔误pubsh_back->push_back
        cout << "\n添加元素: " << t << endl;
        // 若容量不足则扩容
        if (first_free == end) {
            reAllocate();
        }
        // 构造新元素并移动指针
        alloc.construct(first_free, t);
        ++first_free;
        cout << "添加完成。当前大小: " << size()
            << ",容量: " << capacity() << endl;
    }

    // 获取当前元素数量
    size_t size() const {
        return first_free - element;
    }

    // 获取当前容量(可容纳的最大元素数)
    size_t capacity() const {
        return end - element;
    }

    // 重载[]运算符:访问元素
    T& operator[](size_t index) {
        return element[index];
    }
    const T& operator[](size_t index) const {
        return element[index];
    }

    // 打印容器内容
    void print() const {
        cout << "容器内容: [";
        for (const T* p = element; p != first_free; ++p) {
            if (p != element) cout << ",";
            cout << *p;
        }
        cout << "]" << endl;
        cout << "大小: " << size() << "; 容量: " << capacity() << endl;
    }
};

// 演示底层内存操作:分配原始内存->构造对象->销毁对象->释放内存
void demonstrateMemoryOperation() {
    cout << string(30, '=') << endl;
    cout << "演示底层内存操作" << endl;
    cout << string(30, '=') << endl;

    // 1. 分配原始内存(仅分配空间,不构造对象)
    cout << "使用operator new[]分配原始内存" << endl;
    void* raw_memory = operator new[](sizeof(int) * 5);  // 分配5个int的内存
    cout << "分配的内存地址:" << raw_memory << endl;

    // 2. 在指定内存位置构造对象(placement new)
    cout << "\n在指定位置构造对象(placement new)" << endl;
    int* int_array = static_cast<int*>(raw_memory);
    for (int i = 0; i < 5; i++) {
        // 在已分配的内存上构造int对象(不分配新内存)
        new(int_array + i) int(i * 10);  // placement new语法
        cout << "在地址" << (int_array + i) << "构造了值:" << i * 10 << endl;
    }

    // 3. 使用构造好的对象
    cout << "\n构造完成的数组内容:" << endl;
    for (int i = 0; i < 5; i++) {
        cout << int_array[i] << " ";
    }
    cout << endl;

    // 4. 释放内存(对于基础类型可直接释放,复杂类型需先析构)
    cout << "\n释放原始内存" << endl;
    operator delete[](int_array);  // 释放内存块
}

// 测试用自定义类:用于验证对象的构造/析构行为
class TestClass {
private:
    int value;
    string name;

public:
    // 构造函数
    TestClass(int v, const string& n) : value(v), name(n) {
        cout << "TestClass构造: " << name << "(" << value << ")" << endl;
    }

    // 拷贝构造函数
    TestClass(const TestClass& other) : value(other.value), name(other.name) {
        cout << "TestClass拷贝构造: " << name << "(" << value << ")" << endl;
    }

    // 析构函数
    ~TestClass() {
        cout << "TestClass析构: " << name << "(" << value << ")" << endl;
    }

    // 重载输出运算符:便于打印
    friend ostream& operator<<(ostream& os, const TestClass& obj) {
        os << obj.name << "(" << obj.value << ")";
        return os;
    }
};

// 主函数:测试所有功能
int main() {
    cout << string(60, '=') << endl;
    cout << "C++内存机制与Allocator演示" << endl;
    cout << string(60, '=') << endl;

    // 1. 演示底层内存操作
    demonstrateMemoryOperation();

    // 2. 测试int类型的SimpleVector
    cout << "\n" << string(60, '=') << endl;
    cout << "测试int类型的SimpleVector" << endl;
    cout << string(60, '=') << endl;
    SimpleVector<int> int_vec;
    for (int i = 0; i <= 8; i++) {  // 插入9个元素,触发多次扩容
        int_vec.push_back(i);
        int_vec.print();
    }

    // 3. 测试自定义类型的SimpleVector
    cout << "\n" << string(60, '=') << endl;
    cout << "测试TestClass类型的SimpleVector" << endl;
    cout << string(60, '=') << endl;
    SimpleVector<TestClass> class_vec;
    class_vec.push_back(TestClass(1, "obj1"));  // 临时对象->拷贝构造
    class_vec.push_back(TestClass(2, "obj2"));
    class_vec.push_back(TestClass(3, "obj3"));

    cout << "\n最终容器内容:" << endl;
    class_vec.print();

    cout << "\n" << string(60, '=') << endl;
    cout << "程序结束,开始析构..." << endl;
    cout << string(60, '=') << endl;
    return 0;
}


实验结果

1. 演示底层内存操作

在这里插入图片描述

2. 测试int类型的SimpleVector

在这里插入图片描述
在这里插入图片描述

3. 测试自定义类型的SimpleVector

在这里插入图片描述

4. 析构

在这里插入图片描述

更多推荐