简体   繁体   English

我不明白为什么这个函数“从列表中返回一个指针”

[英]I don't understand why this function “returns a pointer from the list”

The book I'm reading, Introduction to Data Structures with Linked Lists (Presentation 21) , has 2 examples of linked lists. 我正在阅读的书,链接列表数据结构简介(演示文稿21) ,有2个链表的例子。 Here is the first one: 这是第一个:

EnemySpaceShip* getNewEnemy ()
{
    EnemySpaceShip* p_ship = new EnemySpaceShip;
    p_ship->x_coordinate = 0;
    p_ship->y_coordinate = 0;
    p_ship->weapon_power = 20;
    p_ship->p_next_enemy = p_enemies;
    p_enemies = p_ship;
    return p_ship;
}

The second example of linked lists is this one: 链接列表的第二个示例是这样的:

EnemySpaceShip* addNewEnemyToList (EnemySpaceShip* p_list)
{
    EnemySpaceShip* p_ship = new EnemySpaceShip;
    p_ship->x_coordinate = 0;
    p_ship->y_coordinate = 0;
    p_ship->weapon_power = 20;
    p_ship->p_next_enemy = p_list;
    return p_ship;
}

Then the book writes this: 然后这本书写道:

Notice that this function differs from getNewEnemy because it returns a pointer to the list, rather than the new enemy. 请注意,此函数与getNewEnemy不同,因为它返回指向列表的指针,而不是新的敌人。

What I don't understand is what he means by the "second function returns a pointer to the list" and "the first function returns the new enemy". 我不明白的是他的意思是“第二个函数返回一个指向列表的指针”和“第一个函数返回新的敌人”。 I thought that they have both created a new enemy called p_ship (which is both a pointer and a new enemy) and returned it. 我以为他们都创造了一个名为p_ship的新敌人(它既是指针也是新敌人)并将其归还。 What is meant by this statement? 这句话是什么意思?

This is the important line 这是重要的路线

p_ship->p_next_enemy = p_list;

Notice that the p_ship has a pointer to p_next_enemy which is itself a EnemySpaceShip* . 请注意, p_ship有一个指针指向p_next_enemy这本身就是一个EnemySpaceShip* Therefore if you kept calling this function over and over, you'd end up with a linked list. 因此,如果你一遍又一遍地调用这个函数,你最终会得到一个链表。 You could start at the first EnemySpaceShip* and traverse all of them in a loop, eg 您可以从第一个EnemySpaceShip*开始,并在循环中遍历所有这些,例如

EnemySpaceShip* p_ship = p_first_ship;    // assume this was known
while (p_ship->p_next_enemy != nullptr)
{
    p_ship = p_ship->p_next_enemy;
    // p_ship has now advanced one element of your linked list
}

Also, due to the order that these ships are being added, if you called addNewEnemyToList several times, the very last time you called it you'd actually get a pointer to the first ship in the linked list. 此外,由于添加这些船只的顺序,如果您多次调用addNewEnemyToList ,则在您最后一次调用它时,您实际上会获得指向链接列表中第一艘船的指针。 That is why the author says "it returns a pointer to the list". 这就是为什么作者说“它返回一个指向列表的指针”。

I don't think the sentence makes any sense. 我认为这句话没有任何意义。

There is only one difference between the functions. 这些功能之间只有一个区别。 In the first function the list of ships is global relative to the function. 在第一个函数中,船只列表相对于函数是全局的。 Perhaps it is a data member of a class and the function is a member function of the class that has access to data members of the class. 也许它是类的数据成员,函数是可以访问类的数据成员的类的成员函数。 Or indeed the list is declared in the global namespace. 或者实际上列表是在全局命名空间中声明的。

In the second function the list is passed to the function as an argument. 在第二个函数中,列表作为参数传递给函数。

The both functions return pointer to the first nodes of the lists. 这两个函数返回指向列表的第一个节点的指针。

If to remove non-important code from the functions and make the names of the lists identical then you will get 如果要从函数中删除不重要的代码并使列表的名称相同,那么您将获得

EnemySpaceShip* getNewEnemy ()
{
    EnemySpaceShip* p_ship = new EnemySpaceShip;
    //...
    p_ship->p_next_enemy = p_enemies;
    p_enemies = p_ship;
    return p_ship;
}


EnemySpaceShip* addNewEnemyToList (EnemySpaceShip* p_enemies)
{
    EnemySpaceShip* p_ship = new EnemySpaceShip;
    //...
    p_ship->p_next_enemy = p_enemies;
    return p_ship;
}

As you see the functions differ only in one statement 如您所见,函数仅在一个语句中有所不同

p_enemies = p_ship;

that is present in the first function (because it has access to the original list itself) and is absent in the second function because the function has only a copy of the head of the list (changing a copy of the head of the original list does not change the original head itself because parameters are local variables of functions). 在第一个函数中存在(因为它可以访问原始列表本身)并且在第二个函数中不存在,因为该函数只有列表头部的副本(更改原始列表头部的副本)不改变原始头本身,因为参数是函数的局部变量)。

You can call the both functions the following way 您可以通过以下方式调用这两个函数

p_enemies = getNewEnemy();

p_enemies = addNewEnemyToList( p_enemies );

and as result p_enemies will be the same list to which a node was added. 因此,p_enemies将与添加节点的列表相同。

Only in the first function is the list also changed within the function; 仅在第一个函数中,该函数内的列表也发生了变化; in the second function you need to assign the return pointer to the list because within the function the list itself is not changed. 在第二个函数中,您需要将返回指针分配给列表,因为在函数内,列表本身不会更改。

Thus I can conclude that the sentence only confuses readers. 因此,我可以得出结论,这句话只会让读者感到困惑。 It should be rewritten somehow to make clear what the author was going to say. 它应该以某种方式重写,以明确作者将要说的内容。 :) It is very important in books for beginners that all sentences be clear. :)在初学者的书中,所有句子都清楚是非常重要的。

The first getNewEnemy uses a field p_enemies , which holds the list of enemies. 第一个getNewEnemy使用一个字段p_enemies ,它保存敌人列表。 It adds itself to the front of the list, by changing p_enemies . 它通过改变p_enemies将自己添加到列表的前面。

The second addNewEnemyToList uses a parameter p_list but it leaves p_list unmodified (as it is an input parameter). 第二个addNewEnemyToList使用参数p_list但它保持p_list (因为它是一个输入参数)。 Hence the result should in all reasonability be assigned to p_list to let that list grow by one. 因此,结果应该在所有合理性中分配给p_list以使该列表增加1。

One would expect: 人们会期望:

p_enemies = addNewEnemyToList(p_enemies);

Though both are pointers to a new enemy, to maintain the list, addNewEnemyToList can be said to return the new list too. 虽然两者都是指向新敌人的指针,但为了维护列表, addNewEnemyToList也可以说是返回新的列表。

I agree with Vlad and was going to simply up vote that answer, but if you look at the two methods from a blackbox perspective, neither imply where the new enemy will be added. 我同意弗拉德并且只是简单地对这个答案进行投票,但是如果你从黑盒子的角度来看这两种方法,都不会暗示新敌人会被添加到哪里。

The name of the first method indicates that the newly created enemy is what will be returned. 第一种方法的名称表示新创建的敌人将被返回。 A side effect is that it is being added to a p_enemies list. 副作用是它被添加到p_enemies列表中。 This in my mind would be a violation of the single responsibility principle, but that might be alleviated with more context around that method. 在我看来,这将违反单一责任原则,但可以通过围绕该方法的更多背景来缓解这一点。 If the method is updated to add the new item to the end or based on a sorted order then it would no longer be returning the head of the list. 如果更新方法以将新项目添加到结尾或基于排序顺序,则它将不再返回列表的头部。

The second method explicitly says it is adding a new enemy to the passed in list. 第二种方法明确表示它正在向传入的列表添加新的敌人。 It is not clear from the definition what is returned and this could be confusing. 从定义中不清楚返回什么,这可能会令人困惑。 Should it return the new enemy or the updated list? 它应该返回新的敌人还是更新后的名单? If it doesn't return the list then can the caller be certain that the new item is at the head of the list? 如果它没有返回列表,那么调用者可以确定新项目是否在列表的头部? What if the requirements change and the new item is to be added to the end of the list? 如果需求发生变化并且新项目要添加到列表末尾怎么办? Not an efficient way to add enemies, but it is possible. 不是添加敌人的有效方式,但它是可能的。

It seems that the book may be trying to point out that the second function is supposed to return the head of the list and not the new enemy. 似乎这本书可能试图指出第二个函数应该返回列表的头部而不是新的敌人。 In this case, the fact that the head of the list is the new enemy is coincidental. 在这种情况下,列表的头部是新的敌人的事实是巧合。

You could even say that the function getNewEnemy() can be replaced by addNewEnemyToList(NULL) 你甚至可以说函数getNewEnemy()可以被addNewEnemyToList(NULL)替换

EnemySpaceShip* getNewEnemy ()
{
  p_enemies = addNewEnemyToList( NULL );
  return p_enemies;
}

or even removed if you use: 如果你使用,甚至删除:

p_enemies = addNewEnemyToList( NULL );
p_enemies = addNewEnemyToList( p_enemies );

I think that the author would mean that the first function is intended to assign an "enemy" pointer type, the second function is intended to assign a "list of enemy" pointer type. 我认为作者将意味着第一个函数旨在分配一个“敌人”指针类型,第二个函数旨在分配一个“敌人列表”指针类型。

The type used for implementing these pointers it is the same, but the meaning of them it is different as well as their using in the program logic flow. 用于实现这些指针的类型是相同的,但它们的含义以及它们在程序逻辑流程中的使用是不同的。

So the author says: attention, in the second case you are getting something that in the program you are going to use as a list, not as a list item... 所以作者说:关注,在第二种情况下,你得到的东西在程序中你将用作列表,而不是列表项...

For example, in this specific case the second function should have to assign the p_list parameter at his exit, otherwise the p_list continues to pointing the previous enemy object. 例如,在这种特定情况下,第二个函数必须在其出口处分配p_list参数,否则p_list继续指向前一个敌对象。

Also consider that it is more likely that getNewEnemy is intended for work with an abstract data type or object, and addNewEnemyToList is intended for work in a "procedural" style.. 还要考虑getNewEnemy更有可能用于处理抽象数据类型或对象,addNewEnemyToList用于“程序”样式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM