【问题标题】:Vector::push_back() gives read access violationVector::push_back() 给出读取访问冲突
【发布时间】:2018-05-05 13:09:24
【问题描述】:

我的类有一个问题,似乎只有在我尝试将我的一个对象添加到向量时才会出现。

分配工作正常除非在尝试插入向量时发生(这会在释放内存时导致以下错误:抛出异常:读取访问冲突this->elements0xCEDECEDF)。

这是我的赋值运算符和我的复制构造函数。注意elements 是一个int** 指针。

    Matrice& Matrice::operator=(const Matrice& other)
{
    if (elements)
    {
        for (size_t i = 0; i < numberoflines; ++i)
            if (elements[i])
                delete[] elements[i];
        delete[] elements;
    }
    id = other.id;
    numberofcols= other.numberofcols;
    numberoflines= other.numberoflines;
    elements = new int*[numberoflines];
    for (size_t i = 0; i < numberoflines; ++i)
        elements[i] = new int[numberofcols];
    for (size_t i = 0; i < numberoflines; ++i)
        for (size_t j = 0; j < numberofcols; ++j)
            elements[i][j] = other.elements[i][j];
    return *this;
}
Matrice::Matrice(const Matrice& other) {
    *this = other;
}

这是Matrice(Matrix) 类的标题:

#pragma once
#include<iostream>
class Matrice {
public:
    friend std::istream& operator>>(std::istream&, Matrice&);
    friend std::ostream& operator<<(std::ostream&, const Matrice&);
    Matrice(const unsigned, const unsigned, const unsigned);
    Matrice();
    Matrice(const Matrice&);
    ~Matrice();
    Matrice& operator=(const Matrice&);
    int operator~()const;
    bool operator<(const Matrice&)const;
private:
    unsigned id;
    unsigned numberoflines;
    unsigned numberofcols;
    int** elements;
};

下面是构造函数和析构函数:

    Matrice::Matrice(unsigned id, unsigned numberoflines, unsigned numberofcols) {
    this->id = id;
    this->numberoflines = numberoflines;
    this->numberofcols = numberofcols;
    elements = new int*[numberoflines];
    for (size_t i = 0; i < numberoflines; ++i)
        elements[i] = new int[numberofcols];
}
Matrice::Matrice() {
    numberofcols = 1;
    numberoflines = 1;
    elements = new int*[numberoflines];
    for (size_t i = 0; i < numberoflines; ++i)
        elements[i] = new int[numberofcols];
}
Matrice::~Matrice() {
    if (elements) {
        for (size_t i = 0; i < numberoflines; ++i)
            if (elements[i])
                delete[] elements[i];
        delete[] elements;
    }
}

最后我只是在 ma​​in 中执行此操作:

 std::vector<Matrice> vec;
    Matrice obj;
    vec.push_back(obj);

【问题讨论】:

  • Matrice 类是什么样的?
  • 所有构造函数都初始化elements 成员吗?在现代 C++ 中,很少有任何好的理由使用 newdelete 关键字 - 只需使用 vector 或智能指针即可避免大多数此类问题。
  • 我知道这不是最好的方法,但我受到学校的限制,无法使用 newdelete
  • 它也对我有用。非常感谢。我是这个项目的瓶颈,我讨厌它。但是你有理由解释为什么这可以解决问题吗?
  • 您可能希望在赋值运算符的顶部执行if (this == &amp;other) return *this;,以防止自赋值。

标签: c++ pointers


【解决方案1】:

您的复制构造函数调用赋值运算符。赋值运算符以以下代码开头:

if (elements)
{
    for (size_t i = 0; i < numberoflines; ++i)
        if (elements[i])
            delete[] elements[i];
    delete[] elements;
}

这会导致拷贝构造函数出现问题,因为拷贝构造函数中没有任何东西初始化elements,所以它会指向内存中的一个随机位置。在你的情况下,那是0xCEDECEDF。因此elements 是非零的,它在 C++ 中总是计算为true,所以我上面引用的代码将尝试删除实际上没有分配的内存。

将行 elements = nullptr; 添加到复制构造函数后,elements 的值现在被解释为 false,因此会跳过 if 块,并且不会调用释放代码。

另一种实现in C++11 的方法(恕我直言更明智)是在类声明本身中初始化nullptr

    unsigned numberofcols;
    int** elements = nullptr; // CHANGE HERE
};

这样,编译器将在每次创建新对象时初始化elements,您不必担心忘记在您的构造函数中这样做。

顺便说一句,您的复制构造函数有一个疏忽;您应该首先确保thisother 不是同一个对象。

【讨论】:

    猜你喜欢
    • 2016-06-15
    • 1970-01-01
    • 2022-10-14
    • 2011-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多