这些析构函数调用中哪些被执行了多次?

问题描述 投票:0回答:1

我现在正在学习 C++,之前是 Java。我确实知道我应该使用

vector
而不是数组,但是我也想了解基础知识。

我已经编写了一个结构,我想用双

[]
访问它。这确实有效并且达到了它的目的。但是,当调用析构函数时,我收到错误:

free(): invalid pointer
Aborted (core dumped)

我问了朋友,他也帮不了我。

这是结构:

#pragma once
class BitArray2
{
public:

    int size;
    
    BitArray2();
    BitArray2(int size);

    ~BitArray2();

    bool** bits = nullptr;

    struct Row{
        public:
        int size;
        bool** bits_row = nullptr;
        int index;

        Row(int size, int index, bool** bits_row)
            :size(size), index(index), bits_row(bits_row){}


        ~Row(){
            bits_row = nullptr;
        }

        bool& operator[](int col_index);
    };

    Row** rows = nullptr;

    Row& operator[](int row_index);



};

BitArray2::BitArray2(){
    BitArray2(1);
}

BitArray2::BitArray2(int size)
    :size(size){
    bits = new bool*[size];
    rows = new Row*[size];
    for (int i = 0; i < size; i++)
    {
        rows[i] = new Row(size, i, bits);
        bits[i] = new bool[size];
    }
    
}

BitArray2::~BitArray2(){
    for (int i = 0; i < size; i++)
    {
        delete[] rows[i];
    }
    for (int i = 0; i < size; i++)
    {
        delete[] bits[i];
    }
    delete[] rows;
    delete[] bits;
}

bool& BitArray2::Row::operator[](const int col_index)
{
    if(col_index < size){
        return bits_row[index][col_index];
    }
    else{
        return bits_row[0][0];
    }
}

BitArray2::Row& BitArray2::operator[](int row_index)
{
    if(row_index < size){
        return  *rows[row_index];
    }
    else{
        return *rows[0];
    }
}

我还将给您一个示例应用程序:

BitArray2 b(4);
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            b[i][j] = (j+i)%2 == 0?true:false;
        }
    }
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            if(b[i][j]){
                std::cout << 1;
            }else{
                std::cout << 0;
            }
        }
        std::cout << std::endl;
    }

输出:

1010
0101
1010
0101
free(): invalid pointer
Aborted (core dumped)

所以我猜测,我的析构函数不正确。在我看来,我在某个地方尝试删除一个之前已经被不同的析构函数删除的对象。我首先删除了

rows
,它保存了对
bits
指针的引用,我将指针设置为
nullptr
,我命令析构函数不要删除顶部
bits
指针数组。也许这不起作用,因为
rows
结构体中的指针与一般
BitArray2
结构体中的指针相同。

我希望获得有关问题所在的更多信息,或者我可以研究一些来源以了解我遇到的问题。

c++ destructor
1个回答
0
投票

大部分问题都在评论中指出:

  1. 委托构造函数需要成为基成员初始化的一部分。
  2. BitArray2
    班需要使用“三规则”或“五规则”。
  3. 不必要的复杂功能
    main
  4. 析构函数错误地使用了
    delete[]
    而不是
    delete

下面的代码中标记了修复程序,并提供了一些额外详细信息的注释。寻找

#if FIX_BY_TBXFREEWARE == 1

我还发现了一些其他需要修复的事情:

  1. size
     为零时,下标运算符将失败。通过在构造函数中添加检查来修复。
  2. 可能会发生细微的内存泄漏。请参阅我在构造函数中的注释。
  3. 每当我编码
  4. operator=
     时,我都会自动编码一个 
    const
     版本来配合它。我已经在这里做到了。
  5. 结构体
  6. Row
    不需要析构函数。它不使用运算符
    new
    。因此,不应该使用运算符
    delete
    。这是一个“零规则”结构。
我不知道为什么你需要

bits

rows
,但我没有在这个问题上思考太久。

@PaulMcKenzie 链接到一个

杰出示例,该示例展示了如何正确编码动态分配的二维数组。他的代码值得研究。

// BitArray2.h #pragma once #define FIX_BY_TBXFREEWARE 1 class BitArray2 { public: int size; BitArray2(); BitArray2(int size); ~BitArray2(); #if FIX_BY_TBXFREEWARE == 1 // Class BitArray2 follows the "Rule of Three", // or, possibly, the "Rule of Five". Either way, // I have deleted the copy constructor and // copy-assignment operator, so that they cannot // be invoked. If you need them, you will need to // code "deep-copy" versions of each. BitArray2(BitArray2 const&) = delete; BitArray2& operator=(BitArray2 const&) = delete; #endif bool** bits = nullptr; struct Row { public: int size; bool** bits_row = nullptr; int index; Row(int size, int index, bool** bits_row) : size(size), index(index), bits_row(bits_row) {} #if FIX_BY_TBXFREEWARE == 1 // Struct Row follows the "Rule of Zero". // Nothing was allocated with operator new, // so nothing gets deleted. #else ~Row() { bits_row = nullptr; } #endif bool& operator[](int col_index); #if FIX_BY_TBXFREEWARE == 1 // Support for constant objects bool const& operator[](int col_index) const; #endif }; Row** rows = nullptr; Row& operator[](int row_index); #if FIX_BY_TBXFREEWARE == 1 // Support for constant objects Row const& operator[](int row_index) const; #endif }; // end file: BitArray2.h
// BitArray2.cpp
#include <stdexcept>
#include "BitArray2.h"

#if FIX_BY_TBXFREEWARE == 1
// Fix delegating constructor.
BitArray2::BitArray2() 
    : BitArray2(1)
{}
#else
BitArray2::BitArray2() {
    BitArray2(1);
}
#endif

BitArray2::BitArray2(int size)
    : size(size)
{
#if FIX_BY_TBXFREEWARE == 1
    // The implementation of operator[] requires a non-zero size.
    if (size < 1)
        throw std::invalid_argument("Invalid size");

    // Possible memory leak
    // If the ctor fails, and throws std::bad_alloc, 
    // the dtor will NOT be called. When that happens, 
    // any allocations that DID WORK need to be deleted 
    // here. I have not coded a fix for this.
#endif

    bits = new bool* [size];
    rows = new Row * [size];
    for (int i = 0; i < size; i++)
    {
        rows[i] = new Row(size, i, bits);
        bits[i] = new bool[size];
    }
}

BitArray2::~BitArray2() {
#if FIX_BY_TBXFREEWARE == 1
    // Changed `delete[]` to `delete`.
    for (int i = 0; i < size; i++)
    {
        delete rows[i];
        delete bits[i];
    }
#else
    for (int i = 0; i < size; i++)
    {
        delete[] rows[i];
    }
    for (int i = 0; i < size; i++)
    {
        delete[] bits[i];
    }
#endif
    delete[] rows;
    delete[] bits;
}

bool& BitArray2::Row::operator[](const int col_index)
{
    if (col_index < size) {
        return bits_row[index][col_index];
    }
    else {
        return bits_row[0][0];
    }
}
#if FIX_BY_TBXFREEWARE == 1
// Support for constant objects
bool const&
BitArray2::Row::operator[](const int col_index) const
{
    if (col_index < size) {
        return bits_row[index][col_index];
    }
    else {
        return bits_row[0][0];
    }
}
#endif
BitArray2::Row& BitArray2::operator[](int row_index)
{
    if (row_index < size) {
        return *rows[row_index];
    }
    else {
        return *rows[0];
    }
}
#if FIX_BY_TBXFREEWARE == 1
// Support for constant objects
BitArray2::Row const&
BitArray2::operator[](int row_index) const
{
    if (row_index < size) {
        return *rows[row_index];
    }
    else {
        return *rows[0];
    }
}
#endif
// end file: BitArray2.cpp
// main.cpp
#include <iostream>
#include "BitArray2.h"
int main()
{
    BitArray2 b(4);
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            b[i][j] = (j + i) % 2 == 0 ? true : false;
        }
    }
    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            if (b[i][j]) {
                std::cout << 1;
            }
            else {
                std::cout << 0;
            }
        }
        std::cout << std::endl;
    }
}
// end file: main.cpp
输出:

1010 0101 1010 0101
    
© www.soinside.com 2019 - 2024. All rights reserved.