魔诀 发表于 2015-3-2 17:11:07

贪吃蛇原码的疑问:关于new

这是原码的一部分
struct Snake
{
        Snake():next(NULL), before(NULL)
        {
                pt.x = 0; pt.y = 0;
        }
        Snake(const POINT &npt, Snake *, Snake *);
        POINT        pt;
        Snake * next, * before;
} snake;//定义蛇头
Snake * psLast = NULL, * food = NULL;
void NewFood(HWND hwnd)
{
        food = new Snake();      原码在这儿用new申请了内存
        SYSTEMTIME st;
        GetLocalTime(&st);
        srand(st.wMilliseconds);
        food->pt.x = rand() % XWIDTH, food->pt.y = rand() % YHEIGHT;
        while(GameClient)
        {
                GetLocalTime(&st);
                srand(st.wMilliseconds);
                food->pt.x = rand() % XWIDTH, food->pt.y = rand() % YHEIGHT;
        }
        GameClient = true;
        InvalidateRect(hwnd, NULL, TRUE);
}

//判断前方是否是食物
inline bool IsFood()
{
        if(snake.pt.x == food->pt.x && snake.pt.y == food->pt.y)
                return true;
        else
                return false;
}

//判断是否撞墙或者撞到自己身体
bool TouchWall()
{
        Snake * temp = psLast;
        //超越边界判断
        if(snake.pt.x >= XWIDTH ||
                snake.pt.x < 0 ||
                snake.pt.y < 0 ||
                snake.pt.y >= YHEIGHT)
                return true;
        //碰撞自身身体判断
        while(temp != &snake)
        {
                if(snake.pt.x == temp->pt.x &&
                        snake.pt.y == temp->pt.y)
                        return true;
                temp = temp->before;
        }
        return false;
}
               

void Move(HWND hwnd)
{
        int x, y;//用于记录蛇头的当前位置(未前进时)
        //标记前方是否为食物,默认为不是食物,表示系通常的前进
        Snake * temp = psLast;
       
        //记录蛇头当前坐标
        x = snake.pt.x;
        y = snake.pt.y;
        //测试前进的地方是否是食物,同时将蛇头前进
        switch(direct)
        {
        case UP:
                --snake.pt.y;
                break;
        case DOWN:
                ++snake.pt.y;
                break;
        case LEFT:
                --snake.pt.x;
                break;
        case RIGHT:
                ++snake.pt.x;
                break;
        default:
                break;
        }
        //如果不是食物,作如下处理
        if(!IsFood())
        {
                //最后一节不是蛇头
                if(temp != &snake)
                {
                        GameClient = false;
                        while(temp != snake.next)
                        {
                                temp->pt.x = temp->before->pt.x;
                                temp->pt.y = temp->before->pt.y;
                                temp = temp->before;
                        }
                        temp->pt.x = x;
                        temp->pt.y = y;
                        GameClient = true;
                }
                else//psLast == &snake,即蛇只有蛇头
                        GameClient = false;                               
                if(TouchWall())
                        IsOver = true;                                                //则标记游戏结束
                else
                        GameClient = true;        //不然移动后的蛇头位置标记为有方块了
                InvalidateRect(hwnd, NULL, TRUE);                //刷新游戏区
        }
        //如果是食物,作如下处理
        else
        {
                ++Score;
                food->before = psLast;       把new申请的内存加入链表中
                psLast->next = food;       
               
                if(temp != &snake)
                {       
                        food->pt.x = psLast->pt.x;
                        food->pt.y = psLast->pt.y;
                        while(temp != snake.next)
                        {
                                temp->pt.x = temp->before->pt.x;
                                temp->pt.y = temp->before->pt.y;
                                temp = temp->before;
                        }
                        //temp=snake.next;
                        temp->pt.x = x;
                        temp->pt.y = y;
                }
                else//psLast == &snake,即蛇只有蛇头
                {
                        food->pt.x = x; food->pt.y = y;
                }
                psLast = food;   把申请的内存地址赋给别一个指针
                NewFood(hwnd);   刷新食物,又会用到new
        }
}
整个原码过程都不曾出现delete,这会不会造成内存泄露?

~风介~ 发表于 2015-3-2 17:24:27

本帖最后由 ~风介~ 于 2015-3-2 17:25 编辑

new和delete不都是配套使用的吗?{:5_94:} 《c++ primer plus》第六版里面有强调哦!有空可以看看~{:5_92:}

freeparty 发表于 2015-3-3 12:47:49

注意这里的void NewFood(hwnd)是一个函数而不是new Food(hwnd)。

freeparty 发表于 2015-3-3 12:48:06

要看仔细哦。

魔诀 发表于 2015-3-3 12:59:09

freeparty 发表于 2015-3-3 12:47
注意这里的void NewFood(hwnd)是一个函数而不是new Food(hwnd)。

在这个void NewFood( hwnd ) 函数里会用到 new 来申请内存 。

freeparty 发表于 2015-3-3 13:03:21

没释放不是会造成内存泄漏么。

maikehong 发表于 2015-3-4 04:12:28

{:1_1:}

hehex 发表于 2015-3-4 10:59:14

感觉会产生内存泄露。但是不一定就直接影响程序运行,如果一直玩下去不终止程序,迟早会因泄露造成异常。
New 开的内存都在堆上是不会因为函数的终止而释放的,因此每调用一次NewFood 函数,就会在heap 里开辟一个struct snake 的内存,周而复始一定会泄露的。

machimilk 发表于 2015-3-5 10:11:47

个人认为,产生食物new出来的结构体用的内存,玩一天游戏也不过几兆,所以作者应该忽略了,如果是其他地方,尤其循环里面或者反复调用的new就一定要配对delete,理论上这代码有瑕疵,但是实际上这点泄露应该没什么大问题
页: [1]
查看完整版本: 贪吃蛇原码的疑问:关于new