Vector::push_back() 给出读取访问冲突

Posted

技术标签:

【中文标题】Vector::push_back() 给出读取访问冲突【英文标题】:Vector::push_back() gives read access violation 【发布时间】: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;,以防止自赋值。 【参考方案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 不是同一个对象。

【讨论】:

以上是关于Vector::push_back() 给出读取访问冲突的主要内容,如果未能解决你的问题,请参考以下文章

没有匹配函数调用‘std::vector::push_back(std::string&)’

矢量.push_back

vector::push_back 和 string::push_back 之间的区别?

在展开期间将向量成员推入向量:vector.push_back(vector[0])

std::vector.push_back() 的奇怪(记忆?)问题

正确使用用户定义类型的 std::vector.push_back()