使用初始化程序列表时发生堆损坏错误

时间:2019-04-08 16:23:41

标签: c++ heap-memory initializer-list

我有一个类,在堆上创建一个数组。稍后,我将增加此数组的大小。当构造类时,我初始化了数组。如果在初始化列表中执行此操作,则在增加数组大小时会收到“堆损坏错误”,但如果不使用初始化列表,则不会发生此错误。

请注意,我并没有同时使用这两个构造函数创建类,但当时只使用了其中一个。
使用intailerizer列表时,为什么它不能按预期工作?

template <typename T>
class Vector {
public:
    Vector() noexcept;

    void push_back(const T& t);

private:
    T* m_arr;
    unsigned int m_size;
    unsigned int m_capacity;

    void realloc();

};

template<typename T>
inline Vector<T>::Vector() noexcept
    : m_size(0), m_capacity(1) {
    m_arr = new T[m_capacity];
    // realloc() works fine with this constructor.
}

template<typename T>
inline Vector<T>::Vector() noexcept
    : m_size(0), m_capacity(1), m_arr(new T[m_capacity]) {
    // Error occurs in realloc() with this constructor.
}

template<typename T>
inline void Vector<T>::push_back(const T& t) {
    if (m_size == m_capacity) {
        m_capacity <<= 1;
        realloc();
    }

    m_arr[m_size] = t;
    ++m_size;
}

template<typename T>
inline void Vector<T>::realloc() {
    T* newArr = new T[m_capacity];
    memcpy(newArr, m_arr, m_size * sizeof(T));
    delete[] m_arr; // Error occurs here with initializer list constructor.
    m_arr = newArr;
}

代码崩溃的示例用法:

int main() {
    Vector vec;
    vec.push_back(0);
    vec.push_back(0); // Crashes here
    vec.push_back(0);

    return 0;
}

1 个答案:

答案 0 :(得分:4)

问题

template<typename T>
inline Vector<T>::Vector() noexcept
    : m_size(0), m_capacity(1), m_arr(new T[m_capacity]) {}

位于成员初始值设定项列出工作方式(https://en.cppreference.com/w/cpp/language/initializer_list)的位置。在标题为“ “初始化顺序” ”的部分中,内容为:

  

非静态数据成员按照声明的顺序在   类定义

这意味着由于类定义m_arr(new T[m_capacity])之前 m_capacity(1)被执行,这意味着new[]使用未初始化的变量,从而导致不确定的行为