I have a tree of things that get asked what data they have, coming from the root.
Technically I have lists of items and I want to put these lists together and also sometimes check through all lists if the items contained in them changed since the last call I made to them.
Right now I use a function akin to
virtual std::vector<MyProject::Item *> get_stuff(param_t query);
With an implementation often times akin to
std::vector<MyProject::Item *> get_stuff(param_t query) {
std::vector<MyProject::Item *> result;
for(Item *i : this->inner_collection) {
std::vector<MyProject::Item *> inner = i->get_stuff(query);
result.insert(result.end(), inner.start(), inner.end());
}
return result;
}
As seen above I use a std::vector to pass this along. Is there a better collection type to do these queries? One that is way better and easier to program with when needing to append stuff to one another quite often?
Related
As part of a simulation I'm currently iterating through a large vector of objects looking for those that have an attribute. It seems to me that it would be faster to store the addresses of those objects in another vector of pointers until I no longer need to operate on them... example code would looks like this... I'm not sure about the erase part.
public:
bool studying = false;
void study();
};
void student::study()
{
//Read a book
studying = false;
};
int vector_question_main(int argc, char* argv[])
{
std::vector<student> masterList;
std::vector<student*> studyingList;
student lazy1;
student good1;
good1.studying = true;
student* s = &masterList.at(1);
studyingList.push_back(s);
for (int i = 0; i < studyingList.size(); i++)
{
studyingList.at(i)->study();
if (studyingList.at(i)->studying == false)
{
studyingList.erase(i);
}
}
}
Am I on the right track or is there a "better" way? To help define my situation I won't know in advance how many objects I have or how many I need to track. I will need to iterate over and operate on them allot.
Edit:
Thanks for the initial responses.
#PaulMcKenzie
The hard requirements/statements of qualities I need from my collection of objects so far is that...
it's easily re-sizeable due to wanting to add/remove objects
frequently.
I can iterate over the collection (in no particular order) performing
some action such as getting/setting an attribute or calling a method.
A objects method will only perform some action on its own attributes
based on its own attributes or parameters.
I expect a future requirement will be that I want to only iterate over a smaller subset. prematurely optimising. Thanks #Jack Deeth
I want to store object that are given a certain name.
I wanted to use struct and then store them in a vector, but it was suggested to me that I should rather use a different data structure, a little more simple, but I cant seem to find one.
My current ("complex") solution:
//in header file
struct objStorage{
Classname obj;
string name;
};
vector<objStorage> vec;
//in constructor
objStorage firstObj;
firstObj.obj = new Classname();
firstObj.name = "foo";
vec.push_back(firstObj);
Is there a more simple solution (Data structure)?
I should add that I don't need the structure once I stored (copied?) it in the vector, because this is all happening in another class (constructor) so I don't want any problems when calling the constructor multiple times.
If you want to lookup items by some key, for example a string, the classic thing to use is a map:
std::map<std::string, Classname> items;
std::pair<std::map<std::string, Classname>::iterator, bool> inserted =
items.insert(std::make_pair(std::string("foo"), Classname()));
items["bar"] = Classname();
In this set up, if you really think you want to use pointers, you should consider some form of smart pointer.
There are other options, for example, C++11 introduces other lookup structures - e.g. unordered maps.
I'm currently in the process of making a simple RTS style game in c++.
What i'm wondering is how to handle the creation of new units in the game (ie. making marines from the barrack). How would i store these units?
I was thinking of having a class 'unit' which would then be inherited by specific unit types (ie. marines, firebats, etc) but if i create an array for these (ie. Marines myMarines[20]) that will create a hard cap on these units.
How do i create such an array that can be expanded at will?
Thank you!
The standard library provides them std::vector template for dynamically resizable arrays. A std::vector<Marine> would be the most straightforward alternative to Marines myMarines[20].
However, you probably don't want a separate list for each unit type. It is highly likely that you will want to store all units in the same list, regardless of their type. std::vector<Unit> would sound like the obvious solution but it is not. The problem is that std::vector stores the objects by value. The following would not work right:
std::vector<Unit> v;
v.push_back(Marine("John Doe"));
The problem is that the Marine object will be copied into a Unit object, which is what the vector stores. This kind of copy results in a what is known as slicing: all the Marine specific members will be lost, and only those that exist in Unit will be stored.
One solution to this problem is to store pointers in the vector because copying pointers does not change the objects they point to. But that brings other problems. To store pointers, this means you'll need to allocate the objects dynamically. And that means that now you are responsible for destroying those objects manually. That's a tiresome and error-prone task.
The solution is to store in the vector objects that destroy the dynamically allocated objects automatically, instead of pointers. These objects are known as smart pointers. The simplest one that exists in the standard library is std::unique_ptr.
std::vector<std::unique_ptr<Unit>> v;
v.emplace_back(new Marine("John Doe"));
This is a C++11 feature. If your compiler doesn't support it you can find alternatives in the Boost libraries. Boost even includes a container that acts pretty much like a std::vector of std::unique_ptrs: boost::ptr_vector. That would be another alternative.
You will probably benefit from using an std::vector here. This will allow you to add and remove items at will, and handles dynamic memory allocation internally (without concerning you over the nitty-gritty details!).
Say you want to store a list of marines (denoted by an imaginary class CMarine in the following example):
std::vector<CMarine> marinesList;
Now to add a marine simply do this:
marinesList.push_back( CMarine( <whatever-its-constructor-takes> ) );
To access this marine you can do something like this:
CMarine& marine = marinesList.at( 0 );
marine.someVar = 33;
marine.doMethod();
(I use a reference since CMarine could very well be too bulky to pass around by value efficiently)
You can also loop through all the marines with an iterator like so:
for ( std::vector<CMarine>::iterator _it = marinesList.begin();
_it != marinesList.end(); ++_it );
{
CMarine& marine = *_it;
// Now you can do something with this marine reference
}
UPDATE:
If CMarine is polymorphic, that is, it inherits from a superclass (maybe something like CUnit in your case), and you have a 'global' vector of all units - Georg Fritzsche rightly noted that object slicing could occur (if we are storing by value). Instead you might be better off with a vector of CUnit (smart) pointers like this:
std::vector<std::unique_ptr<CUnit>> unitsList;
// To add a marine:
unitsList.push_back( new CMarine( <whatever-its-constructor-takes> ) );
Read more about vectors here.
Chances are that you don't want a separate container for each of your unit types. Therefore, you'll have to generalise a little and either use something like component based design. Once you have that in place, you'll want an std::vector<GameUnit*> or std::list<GameUnit*> in the first case, and an std::vector<GameUnit> or std::list<GameUnit> in the second case. Either way, you should be using a standard library container to store things.
You can find more information on std::vector and std::list on http://cppreference.com, although your book should already cover them. Also, see
First off, I'd create a Unit class and then subclass your units from it, so you don't have to process a bunch of separate lists. Then, I'd store pointers to the units in:
std::list< Unit * > unitList
A list lets you append however many objects you like, and, while it doesn't allow for rapid access to random members of the list, you can iterate through it easily and not have to worry about it trying to move large amounts of memory around when you delete something out of the middle of it.
One thing I like to do is have a unit register itself with the units list automatically from inside the unit's constructor. So assuming Marine is a subclass of Unit, all I would need to do would be to say:
new Marine(x_pos, y_pos);
...and a new Marine would be created and appended to the list automatically.
At this point, each frame, you can iterate through every Unit in unitList and run the unit's update function (which is a virtual function that is different for each subclass).
After the update loop, run a cleanup loop that iterates through unitsList again, finds all destroyed units, and removes them from the list and deletes them.
I say std::vector ! I usually create a base class of unit (or GameObject as I like to call them) Here's what I would have done:
class GameObject {} // Maybe has virtual methods for the Size, Location and Image?
class Barrack
{
std::vector< GameObject > gameUnits;
public:
// code
void AddUnit() { gameUnits.push_back( GameObject() ); }
void DestroyUnit(int index);
// etc. etc.
}
However, if you don't want to rely too much on inheritance, i.e you have different kinds of units and all of them don't inherit from one base class, you may try this vector_any class I implemented some days ago to hold the sprites of my RPG game:
struct element
{
element( void* data, const std::type_info& info ) : value(data), type( &info ) {}
void* value;
const std::type_info* type;
};
class type_conversion_exception : exception {};
class linked_vector
{
vector< element > stack;
public:
linked_vector() {}
template< typename T > void add_item( T& item )
{
stack.push_back( element( static_cast< void* >( &item ), typeid(item) ) );
}
template< typename T > T& get_item( int index )
{
if ( *( stack[index].type ) == typeid( T ) )
{
return *( static_cast< T* >( stack[index].value ) );
}
else throw type_conversion_exception();
}
};
You can use it for your game units like this.
linked_vector gameUnits;
MilitaryUnit mUnit;
AirUnit aUnit;
gameUnits.add_item( mUnit );
gameUnits.add_item( aUnit );
try{ draw( gameUnits.get_item< MilitaryUnit >(0) ); }
catch( type_conversion_exception e ) { /* error handling */ }
// etc. etc.
The choice between vector and list is a tricky one. Every time you push_back() on the vector, the whole vector is reallocated and copied. A list doesn't have this issue. Neverthless, you could preallocated the vector and have a unit cap - this is fine unless you want effectively 'unlimited' units on a map, but you probably don't.
As for lookup, the vector has constant time lookup for any index, but how often would you want to jump to a particular index? When it comes to iterating over a whole list or vector I don't think there's any performance difference.
Also, when you want to remove a Unit (when it's killed) from a vector you would have some more reallocate and shuffle issues, a list can remove any item much more efficiently.
I'm personally leaning towards a list.
And as already stated the container you choose should hold pointers to the unit base class.
Setting:
A pseudo-random pattern has to be generated. There are several ways / or algorithms availible to create different content. All algorithms will generate a list of chars (but could be anything else)... the important part is, that all of them return the same type of values, and need the same type of input arguments.
It has to be possible to call a method GetRandomPattern(), which will use a random one of the algorithms everytime it is called.
My first aproach was to put each algorithm in it's own function and select a random one of them each time GetRandompattern() is called. But I didn't come up with another way of choosing between them, than with a switch case statement which is unhandy, ugly and inflexible.
class PatternGenerator{
public:
list<char> GetRandomPattern();
private:
list<char>GeneratePatternA(foo bar);
list<char>GeneratePatternB(foo bar);
........
list<char>GeneratePatternX(foo bar);
}
What would be a good way to select a random GeneratePattern function every time the GetRandomPattern() method is called ?
Or should the whole class be designed differently ?
Thanks a lot
Create a single class for each algorithm, each one subclassing a generator class. Put instances of those objects into a list. Pick one randomly and use it!
More generically, if you start creating several alternative methods with the same signature, something's screaming "put us into sibling classes" at you :)
Update
Can't resist arguing a bit more for an object-oriented solution after the pointer-suggestion came
Imagine at some point you want to print which method created which random thing. With objects, it's easy, just add a "name" method or something. How do you want to achieve this if all you got is a pointer? (yea, create a dictionary from pointers to strings, hm...)
Imagine you find out that you got ten methods, five of which only differ by a parameter. So you write five functions "just to keep the code clean from OOP garbage"? Or won't you rather have a function which happens to be able to store some state with it (also known as an object?)
What I'm trying to say is that this is a textbook application for some OOP design. The above points are just trying to flesh that out a bit and argue that even if it works with pointers now, it's not the future-proof solution. And you shouldn't be afraid to produce code that talks to the reader (ie your future you, in four weeks or so) telling that person what it's doing
You can make an array of function pointers. This avoids having to create a whole bunch of different classes, although you still have to assign the function pointers to the elements of the array. Any way you do this, there are going to be a lot of repetitive-looking lines. In your example, it's in the GetRandomPattern method. In mine, it's in the PatternGenerator constructor.
#define FUNCTION_COUNT 24
typedef list<char>(*generatorFunc)(foo);
class PatternGenerator{
public:
PatternGenerator() {
functions[0] = &GeneratePatternA;
functions[1] = &GeneratePatternB;
...
functions[24] = &GeneratePatternX;
}
list<char> GetRandomPattern() {
foo bar = value;
int funcToUse = rand()%FUNCTION_COUNT;
functions[funcToUse](bar);
}
private:
generatorFunc functions[FUNCTION_COUNT];
}
One way to avoid switch-like coding is using Strategy design pattern. As example:
class IRandomPatternGenerator
{
public:
virtual list<int> makePattern(foo bar);
};
class ARandomPatternGenerator : public IRandomPatternGenerator
{
public:
virtual list<int> makePattern(foo bar)
{
...
}
};
class BRandomPatternGenerator : public IRandomPatternGenerator
{
public:
virtual list<int> makePattern(foo bar)
{
...
}
};
Then you can choose particular algorithm depending on runtime type of your RandomPatternGenerator instance. (As example creating list like nicolas78 suggested)
Thank you for all your great input.
I decided to go with function pointers, mainly because I didn't know them before and they seem to be very powerfull and it was a good chance to get to know them, but also because it saves me lot of lines of code.
If I'd be using Ruby / Java / C# I'd have decided for the suggested Strategy Design pattern ;-)
class PatternGenerator{
typedef list<char>(PatternGenerator::*createPatternFunctionPtr);
public:
PatternGenerator(){
Initialize();
}
GetRandomPattern(){
int randomMethod = (rand()%functionPointerVector.size());
createPatternFunctionPtr randomFunction = functionPointerVector.at( randomMethod );
list<char> pattern = (this->*randomFunction)();
return pattern;
}
private:
void Initialize(){
createPatternFunctionPtr methodA = &PatternGenerator::GeneratePatternA;
createPatternFunctionPtr methodB = &PatternGenerator::GeneratePatternB;
...
functionPointerVector.push_back( methodA );
functionPointerVector.push_back( methodB );
}
list<char>GeneratePatternA(){
...}
list<char>GeneratePatternB(){
...}
vector< createPattern > functionPointerVector;
The readability is not much worse as it would have been with the Design Pattern Solution, it's easy to add new algorithms, the pointer arithmetics are capsuled within a class, it prevents memory leaks and it's very fast and effective...
I have lots of (hierachical) data that I show in a TreeView (could be around 20K items or more, including children items). The peculiar problem with my data is that each object shown in the treeview can exist in many treeview items. What I mean by that is that I might have an hierarchy like this one:
Item_A -> Item_B -> ItemC
Item_B -> Item_C
ItemC
Lets assume that Item_A contains Item_B which contains Item_C as it is shown above. This means that my list will also show the hierarchy of Item_B and Item_C. Consider now that something happens to an an object shown as Item_B (e.g name change). Then of course both items
must be updated. Consider now thousands of items in the treeview with complex hierarchies. What strategy would you use to update the treeview? Speed is of course the main concern here but also ease of use and maintenance. Currently I hold internal mappings of list items to objects and vice-versa to find and update items quickly. Is that a correct strategy? By recreating the list after each update I can throw lots of code away, but I wouldn't know which item paths were expanded or collapsed. How could I solve this problem? Should I store expanded paths in an internal container?
Thank you.
PS: Programming language is C++, and GUI lib is QT3.
I did something similar long time ago, using the windows TreeView common control.
What I did was set the CUSTOMDRAW flag, keep a single instance of each possible different node and make each node point to this instance: The 3 Item_C nodes would each have a pointer to the same unique Item_C instance.
So, when I change the data on Item_C I only needed to Invoke InvalidateRect() on the 3 Item_C nodes in order to reflect the changes done on the (single) changed data.
I suppose you could apply the same strategy here.
Use Qt4 model/view if you can use Qt4 in your project.
You will have to write your own model which can be tedious if you've never done so, but once setup you can reference/update multiple instances of the same object easily. Selections/Multiple selection can be handled too.
I'm not a big fan of Qt's model/view implementation (given model/view/controller design pattern is quite old) but it helps to organize data in gUIs
Disable updates using widget->setUpdatesEnabled(false), then edit all you want, and then renable it with widget->setUpdatesEnabled(true).
See the Qt documentation.
I solved a similar problem using the wxWidgets tree control. I used a singleton reference counter to track the objects I was putting in the control, and an iterator to traverse them. Here's an example.
class ReferenceCounter
{
public:
// Singleton pattern. Implementation left up to you.
static ReferenceCounter& get();
void add(const TreeData& data) {
mCounter[data.getId()].push_back(&data);
}
void remove(const TreeData& data) {
const CounterType::const_iterator itr = mCounter.find(data.getId());
if (itr != mCounter.end()) {
ItemType& items = itr->second;
items.erase(std::remove(items.begin(), items.end(), &data), items.end());
if (items.empty()) {
mCounter.erase(itr);
}
}
}
typedef std::vector<TreeData*> ItemType;
ItemType::iterator begin(const TreeData& data) {
const CounterType::const_iterator itr = mCounter.find(data.getId());
if (itr != mCounter.end()) {
return itr->second.begin();
}
// Else condition handling left up to you.
}
ItemType::iterator end(const TreeData& data) {
const CounterType::const_iterator itr = mCounter.find(data.getId());
if (itr != mCounter.end()) {
return itr->second.end();
}
// Else condition handling left up to you.
}
private:
typedef std::map<int, ItemType> CounterType;
CounterType mCounter;
};
class TreeData
{
public:
TreeData() { ReferenceCounter::get().add(*this); }
~TreeData() { ReferenceCounter::get().remove(*this); }
// Get database rows or whatever your tree is tracking.
int getId() const;
};
So given any TreeData, you can look up all the other TreeData's with matching ids in the reference counter. This makes it easy and fast keeping names and stuff up to date. Our tree handles over 1,000,000 nodes without a problem. In my implementation, I wrapped the iteration stuff up in a boost::iterator_facade class for easier use.