析构函数和指向类属性的指针

发布于 2024-12-21 21:07:40 字数 3980 浏览 0 评论 0原文

我有这个类 ChessBoard,这是它的标题:

class ChessBoard
{
    Field** board;
    Color currentColor; 

public:
    ChessBoard();
    ChessBoard(const ChessBoard&);
    Field* findField(std::string);
    ChessBoard& operator = (const ChessBoard&);

    bool checkIfFieldHasFigure(std::string);


    void writeOneState(SahApi*);
    void playAllMoves(std::istream*, SahApi*);
    void playMove(std::string);
    ~ChessBoard();

};

我有它的构造函数,它创建国际象棋棋盘的开始阶段:(相当可怕,我知道:))

ChessBoard::ChessBoard()
{
    int i, j;
    Error err;
    board = new Field*[8];
    if(!board)
    {
        err.writeToOutput(1);
        exit(1);
    }
    for(i = 0; i < 8; i++)
    {
        board[i] = new Field[8];
        if(!board[i])
        {
            err.writeToOutput(1);
            exit(1);
        }
    }
    currentColor = WHITE;
    char c;
    std::string s;
    Figure f;
    for(i = 0; i < 8; i++)
        for(j = 0; j < 8; j++)
        {
            s.clear();
            c = i + 'A';
            s.push_back(c);
            c = j + '1';
            s.push_back(c);
            board[i][j].position.assign(s);

            if((j > 1) && (j < 6))
                board[i][j].hasFigure = 0;
            else board[i][j].hasFigure = 1;

            if((i+j+2) % 2)
                board[i][j].color = WHITE;
            else board[i][j].color = BLACK;

            if( ((j==0)||(j==7)) && ((i==0)||(i==7)) )
            {
                Rook* r = new Rook(((j==0)?WHITE:BLACK), s);
                if(!r)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(r);
            }
            else if( ((i==1)||(i==6)) && ((j==0)||(j==7)) )
            {
                Knight* n = new Knight(((j==0)?WHITE:BLACK), s);
                if(!n)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(n);
            }
            else if( ((i==2)||(i==5)) && ((j==0)||(j==7)) )
            {
                Bishop* b = new Bishop(((j==0)?WHITE:BLACK), s);
                if(!b)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(b);
            }
            else if( (i==3) && ((j==0)||(j==7)))
            {
                Queen* q = new Queen(((j==0)?WHITE:BLACK), s);
                if(!q)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(q);
            }
            else if( (i==4) && ((j==0)||(j==7)) )
            {
                King* k = new King(((j==0)?WHITE:BLACK), s);
                if(!k)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(k);
            }
            else if( (j==1) || (j==6) )
            {
                Pawn* p = new Pawn(((j==1)?WHITE:BLACK), s);
                if(!p)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(p);
            }
        }       
}

我还需要有一个 ChessBoard 的析构函数,如下所示:

ChessBoard::~ChessBoard()
{
    //for(int i = 0; i < 8; i++)
    //  delete board[i];
    delete [] board;
}

其部分被注释掉的原因是我的第一个问题:

1。为什么我不能用上面写的方法删除所有字段? 当我尝试这样做时,程序会出现“块类型有效”错误,我知道这是由于尝试删除不存在的内存而引起的。当我注释掉它时,程序运行得很好。 ChessBoard 是一个 8x8 的矩阵,所以我应该能够像我在这里尝试的那样删除它。

我的第二个问题是:

2。如何删除我的国际象棋棋盘构造函数中存在的指向图形(King、Queen、Rook...)的指针?这很令人困惑,因为这些指针被用作我的国际象棋棋盘的一部分,并且我使用它们直到程序结束。当程序结束时,我需要释放内存,但我不知道如何访问这些指针。这些数字本身会被自动删除,因为它们都是非指针。 我是否需要删除这些指针,因为我一直使用它们直到最后,然后所有内容都被释放?

I have this class ChessBoard, here's its header:

class ChessBoard
{
    Field** board;
    Color currentColor; 

public:
    ChessBoard();
    ChessBoard(const ChessBoard&);
    Field* findField(std::string);
    ChessBoard& operator = (const ChessBoard&);

    bool checkIfFieldHasFigure(std::string);


    void writeOneState(SahApi*);
    void playAllMoves(std::istream*, SahApi*);
    void playMove(std::string);
    ~ChessBoard();

};

And I have its constructor, which creates the beginning stage of chess board: (quite hideous, I know :) )

ChessBoard::ChessBoard()
{
    int i, j;
    Error err;
    board = new Field*[8];
    if(!board)
    {
        err.writeToOutput(1);
        exit(1);
    }
    for(i = 0; i < 8; i++)
    {
        board[i] = new Field[8];
        if(!board[i])
        {
            err.writeToOutput(1);
            exit(1);
        }
    }
    currentColor = WHITE;
    char c;
    std::string s;
    Figure f;
    for(i = 0; i < 8; i++)
        for(j = 0; j < 8; j++)
        {
            s.clear();
            c = i + 'A';
            s.push_back(c);
            c = j + '1';
            s.push_back(c);
            board[i][j].position.assign(s);

            if((j > 1) && (j < 6))
                board[i][j].hasFigure = 0;
            else board[i][j].hasFigure = 1;

            if((i+j+2) % 2)
                board[i][j].color = WHITE;
            else board[i][j].color = BLACK;

            if( ((j==0)||(j==7)) && ((i==0)||(i==7)) )
            {
                Rook* r = new Rook(((j==0)?WHITE:BLACK), s);
                if(!r)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(r);
            }
            else if( ((i==1)||(i==6)) && ((j==0)||(j==7)) )
            {
                Knight* n = new Knight(((j==0)?WHITE:BLACK), s);
                if(!n)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(n);
            }
            else if( ((i==2)||(i==5)) && ((j==0)||(j==7)) )
            {
                Bishop* b = new Bishop(((j==0)?WHITE:BLACK), s);
                if(!b)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(b);
            }
            else if( (i==3) && ((j==0)||(j==7)))
            {
                Queen* q = new Queen(((j==0)?WHITE:BLACK), s);
                if(!q)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(q);
            }
            else if( (i==4) && ((j==0)||(j==7)) )
            {
                King* k = new King(((j==0)?WHITE:BLACK), s);
                if(!k)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(k);
            }
            else if( (j==1) || (j==6) )
            {
                Pawn* p = new Pawn(((j==1)?WHITE:BLACK), s);
                if(!p)
                {
                    err.writeToOutput(1);
                    exit(1);
                }
                board[i][j].putFigure(p);
            }
        }       
}

I also need to have a destructor for ChessBoard, which is something like this:

ChessBoard::~ChessBoard()
{
    //for(int i = 0; i < 8; i++)
    //  delete board[i];
    delete [] board;
}

The reason part of it is commented out is my first question:

1. Why can't I delete all my fields with the above written method? When I try to do it, the program goes into "Block type is valid" error, which I know is caused by trying to delete nonexistent memory. When I comment it out, the program works perfectly. And the ChessBoard is a matrix 8x8, so I should be able to delete it like I tried here.

My second question is:

2. How can I delete the pointers to Figures (King, Queen, Rook, ...) which exist in my constructor for Chess Board? It's confusing because those pointers are used as parts of my Chess Board, and I use them until the end of the program. When the program ends, I need to free my memory, but I don't know how to access those pointers. The Figures themselves get auto-deleted because they are all non-pointers. Do I even need to delete those pointers, seeing as I use them until the end, and then everything is released?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

捶死心动 2024-12-28 21:07:40
  1. 新建/删除的一般规则是调用必须彼此匹配。您使用

    创建您的板

    board = 新字段*[8];
    for(i = 0; i < 8; i++)
    {
        板[i] = 新字段[8];
    }
    

    您将需要以相同的方式删除您的板,但向后:

    for(i = 0; i < 8; i++)
    {
        删除[]板[i];
    }
    删除[]板;
    

    由于这不起作用,我猜测您的问题是重复删除。其他东西正在释放数组。您是否有可能拥有指向同一 Field** 的 ChessBoard 副本?

  2. 您必须以类似的方式删除您的数字。

    for (int x = 0; x < 8; x ++)
    for (int y = 0; y < 8 ;y ++)
    if (板[y][x]!= NULL)
         删除板[y][x];
    

    只要从板上删除图形的代码会删除该图形并将该图形的位置设置为 NULL,此代码就会起作用。

    2b。你的第二个问题的第二部分是你是否必须执行任何删除操作,因为程序正在结束。你是对的,如果你要立即退出,你不需要删除任何东西,操作系统无论如何都会为你释放所有内存。

不过,您通常应该这样做,通常您最终会通过允许多次运行来修改大多数程序,然后您出现内存泄漏,因为每次运行都会使用稍多的内存。


这就是如何按照要求解决您的问题。
但是,我强烈建议您更改大部分代码的样式并删除所有动态分配。

首先,使用常规静态大小的数组 (Field[8][8]) 来存储字段。我的意思是,棋场什么时候会改变大小?

其次,按值存储碎片。您的字段类已经存储了碎片是否位于某个位置。还让 Field 类存储一个表示类型的枚举。
没有理由为您的作品使用动态分配。

第三,不需要检查new的返回是否为NULL。如果出现错误,它将抛出异常,并且您的程序将停止(理应如此,当内存不足时您无能为力)。

  1. The general rule for new/delete is that the calls have to match each other. You create your board with

    board = new Field*[8];
    for(i = 0; i < 8; i++)
    {
        board[i] = new Field[8];
    }
    

    You are going to need to delete your board the same way, but backwards:

    for(i = 0; i < 8; i++)
    {
        delete [] board[i];
    }
    delete[] board;
    

    Since this is not working I am guessing your issue is double deleting. Something else is freeing the array. Is it possible you have a copy of ChessBoard that is pointing to the same Field**?

  2. You are going to have to delete your figures in a similar way.

    for (int x = 0; x < 8; x ++)
    for (int y = 0; y < 8 ;y ++)
    if (board[y][x] != NULL)
         delete board[y][x];
    

    This code will work as long as your code to remove a figure from the board deletes that figure and sets the position of that figure to NULL.

    2b. The second part of your 2 question was whether you have to do any of this deleting at all, because the program is ending. You are right, in that you do not need to delete anything if you are going to quit right away anyways, the OS will release all that memory for you anyways.

You generally should though, usually you end up modifying most programs by allowing them to run multiple times, and then you will have a memory leak as each run uses slightly more memory.


That is how to solve your question as asked.
However, I would heavily suggest you to change the style of much of this code and remove all of the dynamic allocation.

First, use a regular static sized array (Field[8][8]) to store the field. I mean, when does a chess field ever change size?

Second, store pieces by value.Your field class already stores if a piece is in a location. Also have the Field class store an enum representing the type as well.
There is no reason to use dynamic allocation for your pieces.

Third, there is no need to check if the return of new is NULL. If there is an error, it will throw an exception, and your program will stop(as it should, there is not much you can do when you are out of memory).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文