Should you put executable code in linked list nodes?
#1 Members - Reputation: 209
Posted 15 December 2012 - 06:30 PM
Is it acceptable to make them nodes in a linked list, executable code and all?
I asked one of my friends about it, and he told me to look up function pointers.
Could someone explain this to me in detail?
Baby, make your move, step across the line,
touch me one more time, come on, dare me! I wanna take you on, I know I can't lose,
#2 Crossbones+ - Reputation: 1064
Posted 15 December 2012 - 08:04 PM
In any case, I'm pretty sure this is not a problem you need function pointers for.
Edited by Stroppy Katamari, 15 December 2012 - 08:04 PM.
#3 Members - Reputation: 209
Posted 15 December 2012 - 08:13 PM
Baby, make your move, step across the line,
touch me one more time, come on, dare me! I wanna take you on, I know I can't lose,
#4 Members - Reputation: 1811
Posted 15 December 2012 - 08:18 PM
Sounds like you're thinking of making an Enemy class that both acts as its own linked-list node and as an enemy character. Based on The Single Responsibility Principle I would advise against that.I mean, can I organize my enemy class in a linked lists where each enemy object is a node that has data, as well as actions that they can execute. I looked it up, but all the literature I found doesn't say anything about nodes using functions, only storing data.
Instead, think of it this way: An enemy object *is* the data in a linked-list node.
In C++ this is actually really easy to do since there is already a linked-list container:
std::list<Enemy> linkedListOfEnemies;
Edited by dmatter, 15 December 2012 - 08:19 PM.
#5 Members - Reputation: 209
Posted 15 December 2012 - 09:32 PM
I just didn't really know if the object was considered data or not. So it's perfectly fine right?
And how would I implement it without the standard container, from scratch?
Baby, make your move, step across the line,
touch me one more time, come on, dare me! I wanna take you on, I know I can't lose,
#6 Members - Reputation: 209
Posted 15 December 2012 - 11:22 PM
Baby, make your move, step across the line,
touch me one more time, come on, dare me! I wanna take you on, I know I can't lose,
#7 Members - Reputation: 1102
Posted 16 December 2012 - 12:36 AM
Exactly.Nevermind, I understand now. The data the node holds should be an enemy object, right.
And yes, in an OO language (like C++) an "object" is valid data to be in a variable or list ... and the fact that you can call that data object's methods is totally normal.
#8 Marketplace Seller - Reputation: 8962
Posted 16 December 2012 - 12:52 AM
std::vector<Enemy> enemies; unsigned currentEnemy = 0; enemies[currentEnemy].DoSomething(); currentEnemy++; if(currentEnemy >= enemies.size()) currentEnemy = 0;
You certainly could have enemies in a linked list, but what are you hoping to get out of that?
What are you wanting to do, that std::vector can't do for you? Dynamic arrays (like std::vector) have their pros and cons, and linked lists have their pros and cons. It most situations, though, the cons of std::vector are so minor that unless you are trying to hyper-optimize something, or are dealing with a staggering amount of data, it really doesn't make sense to not use it.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal
#9 Members - Reputation: 209
Posted 17 December 2012 - 12:15 AM
Baby, make your move, step across the line,
touch me one more time, come on, dare me! I wanna take you on, I know I can't lose,
#10 Marketplace Seller - Reputation: 8962
Posted 17 December 2012 - 12:41 AM
One drawback is element access speed - random access to an array is very very fast. Random access to a linked list is very very slow.
The benefits of linked lists are:
A) Fast inserting/removing in the front, back, or the middle.
The cons are:
B) Slow random-access.
The benefits of a vector are:
A) Fast inserting/removing from the back, with an occasional reallocation cost.
B) Fast random access.
The cons of a vector are:
A) Slow inserting/removing to the front or middle.
Each are equally good at "iterating in a loop" - in theory; though in reality I wouldn't be surprised if a vector outpaced the list.
However, if the real Pro vs Con is, "optimized for resizing, moving, removing" verses "optimized for accessing", then you have to ask yourself, how frequently do you insert/remove verses how frequently do you access or iterate?
If you add and destroy 200 enemies a frame, then a list might be preferable (though I'd still use a vector, personally, and just flag 'dead' enemies for reuse).
But more than likely, you add/destroy an enemy occasionally, but iterate over multiple enemies every frame.
It's really not a big deal whichever you go with, and overthinking it would be premature optimization... but the "proper" choice, if I'm understanding what you are wanting, is a vector - and it's good to know when to use what tool, and why it's better or worse in what situations.
Again, if your only reason for using a linked list is for circular iteration, then here is a circularly iterating vector:
myVector[index %= myVector.size()].DoSomething();
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal
#11 Members - Reputation: 209
Posted 17 December 2012 - 03:10 AM
The maximum amount of enemies on screen will be somewhere around 20, but no greater, I think. Only one enemy can die at a time; it is not possible to kill two at once. They are first flagged dead, then deleted, and it happens with a "death freeze frame", as in, all action freezes to let the enemy's dying animation play out, so computing time will probably not be noticably affected by moving data around. There is nothing graphics-intensive, as it is all run in command prompt and all sprites are character-based. I have no graphics to worry about. I will never have to worry about randomly accessing them because they're moved in sequence.
I made another thread about my enemies' data management and the people in the thread told me that I should not just flag the enemies dead, which is what I did before, and that I should delete enemies when they've been killed. So I've been working with that intent in mind. If you can convince me to do otherwise, then I'll change my method.
Baby, make your move, step across the line,
touch me one more time, come on, dare me! I wanna take you on, I know I can't lose,
#12 Marketplace Seller - Reputation: 8962
Posted 17 December 2012 - 09:40 AM
You probably don't need to mark and delete enemies, you can just delete them without marking them in a list (unless you need them marked for unrelated reasons).
If using vectors, you can mark them without deleting them, or using the "swap to end" trick if element ordering is insignificant.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal
#13 Members - Reputation: 751
Posted 17 December 2012 - 10:14 AM
http://www.baptiste-wicht.com/2012/11/cpp-benchmark-vector-vs-list/
If this post was helpful and/or constructive please give rep.
SFML2.0 Nightly Download Link http://en.sfml-dev.org/forums/index.php?topic=9513.0
SFML2.0 Tutorials http://www.sfml-dev.org/tutorials/2.0/
#14 Members - Reputation: 5900
Posted 17 December 2012 - 10:28 AM
#15 Moderators - Reputation: 5066
Posted 17 December 2012 - 10:48 AM
Not quite. If you have a C++ object that has virtual functions, the size of the object is more than just the data. It isn't that the code is included in the object, but typical implementations include an indirect reference to the code (usually via a VTable pointer).An object is just the data. Then we provide a bunch of functions that act on the data, and we put that in the same block as a way of mentally organizing things, but when you compute the size of an object, you only get the size of the data, not the code. It would be good to be clear about this when introducing someone to objects.
You cannot, in general, sensibly write non-POD types to a file directly.When you write an object to a file, only the data is written.
#16 Members - Reputation: 209
Posted 17 December 2012 - 11:41 AM
Edited by StoneMask, 17 December 2012 - 11:46 AM.
#17 Marketplace Seller - Reputation: 8962
Posted 17 December 2012 - 12:11 PM
However, it is of very significant benefit to roll your own containers for learning experience - so don't let me discourage you from that! But at the same time, you have to be willing to discard your own containers and go back to the tried and true, heavily optimized, heavily debugged standard containers after you practice with your own. This is hard for alot of people, because they want to use their own after all the work they put into it ("And why not, after I spent two weeks on it?"), and sometimes, overtime, they get caught into NIH and YAGNI - both which leads to not actually finishing projects, and instead just working on the sub-projects without actually releasing anything real - of which programming culture is far too filled with.
That is my personal opinion - other people's opinion will vary. You are intelligent enough to analyze the data yourself (now that you know there is data to analyze) and then decide what, in your personal and unique circumstances, is the best option at the present situation, and the best option for future situations. My (and everyone's) armchair guesses at what's best for your current project should always be taken as counsel but not law, as it may be flawed from us not having all the details that you alone possess.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal
#18 Members - Reputation: 5900
Posted 17 December 2012 - 01:14 PM
To clarify:
Not quite. If you have a C++ object that has virtual functions, the size of the object is more than just the data. It isn't that the code is included in the object, but typical implementations include an indirect reference to the code (usually via a VTable pointer).
An object is just the data. Then we provide a bunch of functions that act on the data, and we put that in the same block as a way of mentally organizing things, but when you compute the size of an object, you only get the size of the data, not the code. It would be good to be clear about this when introducing someone to objects.You cannot, in general, sensibly write non-POD types to a file directly.When you write an object to a file, only the data is written.
I seem to have a problem lately when I try to keep things simple: Someone will come and pick my statements apart, instead of trying to understand what I am saying.
There is a common way to introduce objects out there as something comprising both data and code. At the same level of detail of that statement, I propose an alternative ("Objects are only data, but we write the code that manipulates the data in the same block to keep things neatly organized") to help beginners have some intuition as to what's going on.
When talking to a beginner that is confused enough to think that you store code in a linked list, I think your clarifications hurt more than they help. But yes, they are correct.
#19 Members - Reputation: 751
Posted 17 December 2012 - 01:20 PM
(list) qualities really only shine through when there is a large amount of data being used, and the objects I'm using definitely don't approach a kilobyte.
http://www.baptiste-wicht.com/2012/11/cpp-benchmark-vector-vs-list/
This is true. You should use vector.
Often people argue that if you doing lots of random insertion and deletion that you should use a list. This is clearly not true ( according to the link provided above ), unless you are using LARGE data structures atleast 1KB each and thousands of them. This is because vector's memory is continuous and uses the cpu's cache MUCH more efficiently than a list ever could.
Also if you use the vector properly then you can cut down on some of its bottlenecks. For example in an unsorted vector you should always push_back(), and if you are deleting an object you can switch it with the last one and then delete the last one, this prevents the vector from having to move every element after the one you were going to delete. Also you can reserve memory for a vector so the vector doesn't have to resize itself.
Edited by EddieV223, 17 December 2012 - 01:36 PM.
If this post was helpful and/or constructive please give rep.
SFML2.0 Nightly Download Link http://en.sfml-dev.org/forums/index.php?topic=9513.0
SFML2.0 Tutorials http://www.sfml-dev.org/tutorials/2.0/
#20 Crossbones+ - Reputation: 1064
Posted 19 December 2012 - 10:45 PM
Then, if you have some separate project of your own, you can normally use the standard library container (which will be faster and more reliable than your own), but you can swap in your own container for testing purposes or for the hell of it. You'll increase your understanding of the standard interface, and good interface design, at the same time.
Just typedef it somewhere in your project and you can switch between your own container and standard container with ease.
Edited by Stroppy Katamari, 19 December 2012 - 10:45 PM.






