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

如何在C++中不使用指针或new实现动态数组?

不用手动new/delete实现自定义动态数组的方案

首先明确:动态数组的底层必然依赖指针管理连续堆内存,完全避开指针做不到,但我们可以借助现代C标准库工具,把裸指针、手动new/delete的操作封装起来,让代码更安全、更符合现代C规范——这也是提升编程水平的关键方向。

下面给你两种可行的改进方案:

方案一:用智能指针管理动态数组

std::unique_ptr<T[]>是标准库专门为动态数组设计的智能指针,它会自动在生命周期结束时释放内存,彻底避免手动写delete[]带来的内存泄漏或double free问题。

修改后的Myvector代码示例:

#include <iostream>
#include <memory> // 引入智能指针头文件

template<class T> class Myvector{
private:
    int size;
    int capacity;
    std::unique_ptr<T[]> objects; // 替换裸指针为unique_ptr

    void add_capacity(){
        int newCapacity = capacity * 2 + 1;
        // 用make_unique创建新数组,自动管理内存
        auto newArray = std::make_unique<T[]>(newCapacity);
        for(int i = 0; i < size; ++i){
            newArray[i] = std::move(objects[i]);
        }
        capacity = newCapacity;
        // 交换智能指针,旧数组会被自动释放
        objects.swap(newArray);
    }

public:
    Myvector() : size(0), capacity(1), objects(std::make_unique<T[]>(1)){}

    void add(T obj){
        if(capacity == size){
            add_capacity();
        }
        objects[size] = std::move(obj); // 用move减少拷贝开销
        size += 1;
    }

    // 迭代器逻辑无需修改,智能指针的operator[]返回引用,取地址后仍是指针
    class Iterator{
    public:
        T* operator->() { return ptr; }
        Iterator(T* p) : ptr(p){}

        Iterator operator++(){
            ++ptr;
            return *this;
        }
        bool operator!=(const Iterator& other) const{ return ptr != other.ptr; }
        const T& operator*() const{ return *ptr; }

    private:
        T* ptr;
    };

    Iterator begin() { return Iterator(&objects[0]); }
    Iterator end() { return Iterator(&objects[size]); }
};

方案二:用std::allocator实现高效内存管理

如果想更贴近标准库std::vector的实现逻辑,可以用std::allocator——它把内存分配和对象构造分离,解决了new T[N]会默认构造所有元素的问题(对于无默认构造函数的类型,原代码会直接编译失败),同时完全避开手动new/delete。

修改后的代码示例:

#include <iostream>
#include <memory> // 引入allocator头文件

template<class T> class Myvector{
private:
    int size;
    int capacity;
    std::allocator<T> alloc; // 分配器对象
    T* objects; // 仍需指针,但内存分配由allocator处理

    void add_capacity(){
        int newCapacity = capacity * 2 + 1;
        // 只分配内存,不构造对象
        T* newArray = alloc.allocate(newCapacity);
        // 移动构造现有元素到新内存
        for(int i = 0; i < size; ++i){
            alloc.construct(newArray + i, std::move(objects[i]));
            alloc.destroy(objects + i); // 销毁旧内存中的对象
        }
        alloc.deallocate(objects, capacity); // 释放旧内存
        objects = newArray;
        capacity = newCapacity;
    }

public:
    Myvector() : size(0), capacity(1), objects(alloc.allocate(1)){}

    // 析构函数需手动销毁所有对象并释放内存
    ~Myvector(){
        for(int i = 0; i < size; ++i){
            alloc.destroy(objects + i);
        }
        alloc.deallocate(objects, capacity);
    }

    // 禁用拷贝构造和赋值(需支持的话可自行实现深拷贝)
    Myvector(const Myvector&) = delete;
    Myvector& operator=(const Myvector&) = delete;

    // 实现移动构造和赋值,提升性能
    Myvector(Myvector&& other) noexcept : size(other.size), capacity(other.capacity), objects(other.objects){
        other.size = 0;
        other.capacity = 0;
        other.objects = nullptr;
    }

    Myvector& operator=(Myvector&& other) noexcept{
        if(this != &other){
            // 清理当前资源
            for(int i = 0; i < size; ++i){
                alloc.destroy(objects + i);
            }
            alloc.deallocate(objects, capacity);
            // 转移对方资源
            size = other.size;
            capacity = other.capacity;
            objects = other.objects;
            other.size = 0;
            other.capacity = 0;
            other.objects = nullptr;
        }
        return *this;
    }

    void add(T obj){
        if(capacity == size){
            add_capacity();
        }
        alloc.construct(objects + size, std::move(obj)); // 直接构造新对象
        size += 1;
    }

    // 迭代器逻辑保留
    class Iterator{
    public:
        T* operator->() { return ptr; }
        Iterator(T* p) : ptr(p){}

        Iterator operator++(){
            ++ptr;
            return *this;
        }
        bool operator!=(const Iterator& other) const{ return ptr != other.ptr; }
        const T& operator*() const{ return *ptr; }

    private:
        T* ptr;
    };

    Iterator begin() { return Iterator(objects); }
    Iterator end() { return Iterator(objects + size); }
};

额外提升建议

  1. 实现emplace_back:替代add方法,直接在数组末尾构造对象,避免不必要的拷贝/移动。
  2. 完善迭代器类型:添加iterator_category、value_type等类型定义,让迭代器适配标准库算法。
  3. 添加边界检查:比如实现operator[]时加入越界检查(用assert或抛出异常)。
  4. 补充拷贝语义:如果需要支持拷贝,手动实现拷贝构造和赋值函数,完成深拷贝逻辑。

内容的提问来源于stack exchange,提问作者Ode

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 19:05:44