首页 > 解决方案 > Vector 实现中的 char* 缓冲区

问题描述

我一直在浏览向量/通用内存管理的实现。我在 codereview 上发现了一个问题,但我不明白其中一个建议是如何工作的。

这是问题相关部分的片段(代码):

template <class T>
class  Vector {
public:

    typedef T* Iterator;

    Vector();
    Vector(unsigned int size);
    Vector(unsigned int size, const T & initial);
    Vector(const Vector<T>& v);
    ~Vector();

    unsigned int capacity() const;
    unsigned int size() const;
    bool empty() const;
    Iterator begin();
    Iterator end();
    T& front();
    T& back();
    void push_back(const T& value);
    void pop_back();

    void reserve(unsigned int capacity);
    void resize(unsigned int size);

    T & operator[](unsigned int index);
    Vector<T> & operator = (const Vector<T> &);
    void clear();
private:
    unsigned int _size;
    unsigned int _capacity;
    unsigned int Log;
    T* buffer;
};

参考这个答案,为什么他建议使用char*缓冲区而不是T*缓冲区,更重要的是,它是如何工作的,它是什么意思?我知道 char 指针没有初始化,但我认为你只能使用T*......泛型类型如何适合 char 指针?

答案的相关部分:

如果缓冲区是 T 类型,您将很难完成这项工作。每次扩展缓冲区时,缓冲区中的所有元素都将使用 T 构造函数进行初始化。对于 int 来说,这不是问题。但是如果 T 有一个非平凡的构造函数,那么你将付出沉重的代价来初始化可能永远不会使用的元素。

T* buffer;

实际上,缓冲区应该是没有构造函数的东西。

char* buffer;

标签: c++templates

解决方案


解释就在答案中,

如果缓冲区的类型为 ,您将很难完成这项工作T。每次扩展缓冲区时,缓冲区中的所有元素都将使用T构造函数进行初始化。因为int这不是问题。但是如果T有一个非平凡的构造函数,那么你将付出沉重的代价来初始化可能永远不会使用的元素。

什么时候可以使用

char* buffer_;

所有未使用的元素都buffer_将包含未初始化的数据,但这没关系。您无需为使用非平凡的构造函数初始化每个对象而付出代价,您在使用时必须付出代价

T* buffer_;

@FrançoisAndrieux 提出了另一个有效观点。如果T不是默认可构造的,您将无法使用它new T[capacity]来分配内存。

关于您的评论,char可以使用一组对象来保存任何对象。您只需要分配适当数量的char对象。您必须分配对象capacity数量,而不是对象数量。Tcapacity*sizeof(T)char


推荐阅读