c++ 向量实现在大小达到100后给予访问冲突错误[已关闭]

llmtgqce  于 2023-05-08  发布在  其他
关注(0)|答案(1)|浏览(88)

**关闭。**此题需要debugging details。目前不接受答复。

编辑问题以包含desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem。这将帮助其他人回答这个问题。
5天前关闭。
Improve this question
我尝试在C++中实现自己的vector类。当我试图在代码中使用它,以2D向量存储邻接矩阵时,在将容量增加到100左右后,它会导致访问冲突错误。当我调试代码时,它说向量大小和容量是-84215046。
向量实现

#pragma once
#include <iostream>
using namespace std;

template <typename T> class ownVector {
    T* arr;
    int capacity;
    int size;
public:
    ownVector() {
        arr = new T[1];
        capacity = 1;
        size = 0;
    }
    //~ownVector() {
        //delete[] arr;
    //}
    void push(T data) {
        if (size == capacity) {
            T* temp = new T[capacity + 2];
            for (int i = 0; i < capacity; i++) {
                temp[i] = arr[i];
            }
            //delete[] arr;
            capacity += 2;
            arr = temp;
        }
        arr[size] = data;
        size++;
    }
    T get(int index) const {
        return arr[index];
    }
    void set(int index, T value) {
        arr[index] = value;
    }
    T* begin() const {
        return arr;
    }
    T* end() const {
        return arr + size;
    }
    int getSize() const {
        return size;
    }
    int getCapacity() const {
        return capacity;
    }
    void clear() {
        delete[] arr;
        capacity = 1;
        size = 0;
        arr = new T[1];
    }
};

发生问题的函数

void Flights::addFlight(string startCity, string destination, int time) {
    int u = cities[startCity];
    int v = cities[destination];
    ownVector<int> uRow = graph.get(u);
    ownVector<int> vRow = graph.get(v);
    uRow.set(v, time);
    vRow.set(u, time);
    graph.set(v, vRow);
    graph.set(u, uRow);
}

u和v是分配给给定城市名称的整数,并且指示表示到其他城市的距离的值所在的向量的行和列
我尝试更改与容量相乘的值,并将其更改为加法而不是乘法,但总是发生相同的错误。我希望代码能够正确地存储到位置u,v和v,u上的其他城市的距离值,这样我就可以使用Dijkstra算法找到最短路径并正确地去定位内存,因为当我取消注解时,我收到的解构器也访问违规错误。

qyswt5oh

qyswt5oh1#

我看到的一个主要问题是你的ownVector类根本不遵循Rule of Three**:
如果一个类需要一个用户定义的析构函数、一个用户定义的复制构造函数或一个用户定义的复制赋值运算符,那么几乎可以肯定它需要所有这三个。

  • 析构函数被注解掉,从而导致内存泄漏。
  • 您根本没有实现复制构造函数或复制赋值运算符。默认的编译器生成的实现不足以满足该类的需要。它将创建数组指针的 * 浅 * 副本,从而允许多个ownVector对象共享一个数组。你需要数组的 deep 拷贝。ownVector的每个示例都需要拥有数组。

在C++11和更高版本中,三的规则变成了五的规则:
由于用户定义的(或= default= delete声明的)析构函数、复制构造函数或复制赋值运算符的存在阻止了移动构造函数和移动赋值运算符的隐式定义,因此需要使用移动语义的任何类都必须声明所有五个特殊成员函数

  • 您也没有实现移动构造函数或移动赋值运算符。

您的ownVector类还存在一些其他问题:

  • push()没有delete[]处理旧数组,导致内存泄漏。
  • push()应该只将size数量的元素复制到temp数组中,而不是capacity数量的元素。
  • clear()delete[]后不会将arr重置为空,以防new[]随后抛出。实际上,根本不需要clear()delete[]现有阵列。它应该简单地将size重置为0,但保持现有capacity完整。但是,它至少应该将现有的数组元素重置为默认状态,以允许任何非平凡类型释放它们可能正在管理的资源。

那么,试试这个:

#pragma once
#include <iostream>
using namespace std;

template <typename T>
class ownVector {
    T* arr;
    int capacity;
    int size;

public:
    ownVector() {
        arr = new T[1];
        capacity = 1;
        size = 0;
    }

    ownVector(const ownVector& src) {
        arr = new T[src.capacity];
        capacity = src.capacity;
        size = src.size;
        for (int i = 0; i < size; ++i) {
            arr[i] = src.arr[i];
        }
        // or: std::copy_n(src.arr, src.size, arr);
    }

    ownVector(ownVector&& src) {
        arr = nullptr;
        capacity = 0;
        size = 0;
        src.swap(*this);
    }

    ~ownVector() {
        delete[] arr;
    }

    ownVector& operator=(ownVector rhs) {
        rhs.swap(*this);
        return *this;
    }
    
    void swap(ownVector& other) {
        T* ptr = arr;
        arr = other.arr;
        other.arr = ptr;
        // or: std::swap(arr, other.arr);

        int cap = capacity;
        capacity = other.capacity;
        other.capacity = cap;
        // or: std::swap(capacity, other.capacity);
        
        int sz = size;
        size = other.size;
        other.size = sz;
        // or: std::swap(size, other.size);
    }

    void push(const T& data) {
        if (size == capacity) {
            T* temp = new T[capacity + 2];
            for (int i = 0; i < size; ++i) {
                temp[i] = arr[i];
            }
            // or: std::copy_n(arr, size, temp);
            delete[] arr;
            arr = temp;
            capacity += 2;
        }
        arr[size] = data;
        ++size;
    }

    T& get(int index) {
        return arr[index];
    }

    T get(int index) const { // or: const T&
        return arr[index];
    }

    void set(int index, const T& value) {
        arr[index] = value;
    }

    T* begin() {
        return arr;
    }

    const T* begin() const {
        return arr;
    }

    T* end() {
        return arr + size;
    }

    const T* end() const {
        return arr + size;
    }

    int getSize() const {
        return size;
    }

    int getCapacity() const {
        return capacity;
    }

    void clear() {
        delete[] arr;
        arr = nullptr;
        capacity = 0;
        size = 0;
        arr = new T[1];
        capacity = 1;

        /* or:
        for(int i = 0; i < size; ++i) {
            arr[i] = T();
        }
        or:
        std::fill_n(arr, size, T());

        size = 0;
        */
    }
};

相关问题