I'm trying to understand when I need to allocate an array of an object that each pointer to some object for example array of Student that point to Student:
Student** db = new Student*[size]
when do I need to use it? I know that is a general question, but I'm trying to solve some Exam that combines inheritance, and in some class, one of the data member they declare it as I said above.
in my solution i wrote:
Student * db = new Student[size];
thanks.
TL;DR version:
Use std::vector<std::unique_ptr<Student>> db.
Explanation
Student** db = new Student*[size]
could be used to represent an array of classes derived from Student.
eg:
Student** db = new Student*[size];
db[0] = new Grad_Student();
db[1] = new Coop_Student();
db[2] = new Elementary_Student();
If you elect the second option
Student * db = new Student[size];
db[0] = Grad_Student();
db[1] = Coop_Student();
db[2] = Elementary_Student();
you save a lot of pesky manual memory management by directly holding Students rather than pointers to Students, but Object Slicing will turn the derived Students into plain old Students. A box sized and shaped to fit a Student can only store a Student, so all of the additional features of, for example, the Grad_Student assigned to db[0] will be lost. Only by storing a reference to the Grad_Student can the Grad_Student's extensions be preserved. You just have to remember that the Grad_Student is actually stored somewhere else.
Sounds good right? It is until you look at all of the dynamic allocations you have to make sure are cleaned up. Memory management is one of the hardest things to get right in C++, and one of the best ways to manage memory management is through Resource Allocation Is Initialization or RAII. std::vector and std::unique_ptr are fabulous examples of RAII in action.
vector is a dynamic array all nicely wrapped up inside a class that handles virtually every aspect of list management right down to adding, removing, resizing, and making sure everything gets cleaned up. unique_ptr is a Smart Pointer that ensures exactly one owner of a resource, and this owner will clean up the resource when it is destroyed. The result, std::vector<std::unique_ptr<Student>> will allow you to add, remove, access, and move any Students without any direct intervention. This allows you to write simpler code. Simpler code is less likely to have bugs. Fewer bugs means more leisure time and happier clients. Everybody wins.
Suppose you already have a collection, for example a linked list of Students which is in order by Student ID. You want to sort them by Student last name. Instead of changing your linked list, or messing up its order, you just allocate an array of pointers and sort that. Your original list remains intact but you can do fast binary searches by last name using your array.
Related
I would like to ask about my approach to using pointers raw pointers without allocating any memory using pointers. I am working on an application, that is simulating classical cashdesk. So I have a class CashDesk, which is containing vectors of Items and vector of Orders, which are classes to represent items and orders. Furthermore, I want the Order class to contain a vector, which would be a vector of pointers to Item – I don't want to store the object multiple times in different orders, because it makes no sense to me. Through the pointers in Order, I only want to be able to access properties of the class Item, there is no allocating of memory using the pointers.
Simplified code:
class CashDesk {
vector<Item> items;
vector<Order> orders;
}
class Order {
vector<Item*> ItemsInOrder;
}
Class Item containing only structured data – information about the Item.
I create all objects at the level of the CashDesk class – create instance of Item when needed and push it to items vector.
I have been told that I should avoid using raw pointers unless there is no another option. The important thing is that I don't use any memory allocation using pointers – really using the pointer in terms of pointing at the object and accessing it's properties. Should I rather use something like unique_ptr, or completely different approach?
Thanks for any response.
I have been told that I should avoid using raw pointers unless there is no another option.
You have been told something subtly wrong. You should avoid owning raw pointers, but non-owning raw pointers are perfectly fine.
You will have to ensure that the elements of Order::itemsInOrder aren't invalidated by operations on CashDesk::items, but that co-ordination should be within the private parts of CashDesk.
You could be more explicit about the lack of ownership semantic, by using std::vector<Item>::iterator in place of Item *, but that doesn't change any behaviour (a conforming implementation may implement std::vector<Item>::iterator as an alias of Item *)
I'm developing a game server for a video game called Tibia.
Basically, there can be up to millions of objects, of which there can be up to thousands of deletes and re-creations as players interact with the game world.
The thing is, the original creators used a Slot Map / Object Pool on which pointers are re-used when an object is removed. This is a huge performance boost since there's no need to do much memory reallocation unless needed.
And of course, I'm trying to accomplish that myself, but I've come into one huge problem with my Slot Map:
Here's just a few explanation of how Slot Map works according to a source I found online:
Object class is the base class for every game object, my Slot Map / object Pool is using this Object class to save every allocated object.
Example:
struct TObjectBlock
{
Object Object[36768];
};
The way the slot map works is that, the server first allocates, say, 36768 objects in a list of TObjectBlock and gives them a unique ID ObjectID for each Object which can be re-used in a free object list when the server needs to create a new object.
Example:
Object 1 (ID: 555) is deleted, it's ID 555 is put in a free object ID
list, an Item creation is requested, ID 555 is reused since it's on
the free object list, and there is no need to reallocate another
TObjectBlock in the array for further objects.
My problem: How can I use "Player" "Creature" "Item" "Tile" to support this Slot Map? I don't seem to come up with a solution into this logic problem.
I am using a virtual class to manage all objects:
struct Object
{
uint32_t ObjectID;
int32_t posx;
int32_t posy;
int32_t posz;
};
Then, I'd create the objects themselves:
struct Creature : Object
{
char Name[31];
};
struct Player : Creature
{
};
struct Item : Object
{
uint16_t Attack;
};
struct Tile : Object
{
};
But now if I was to make use of the slot map, I'd have to do something like this:
Object allocatedObject;
allocatedObject.ObjectID = CreateObject(); // Get a free object ID to use
if (allocatedObject.ObjectID != INVALIDOBJECT.ObjectID)
{
Creature* monster = new Creature();
// This doesn't make much sense, since I'd have this creature pointer floating around!
monster.ObjectID = allocatedObject.ObjectID;
}
It pretty much doesn't make much sense to set a whole new object pointer the already allocated object unique ID.
What are my options with this logic?
I believe you have a lot of tangled concepts here, and you need to detangle them to make this work.
First, you are actually defeating the primary purpose of this model. What you showed smells badly of cargo cult programming. You should not be newing objects, at least without overloading, if you are serious about this. You should allocate a single large block of memory for a given object type and draw from that on "allocation" - be it from an overloaded new or creation via a memory manager class. That means you need separate blocks of memory for each object type, not a single "objects" block.
The whole idea is that if you want to avoid allocation-deallocation of actual memory, you need to reuse the memory. To construct an object, you need enough memory to fit it, and your types are not the same length. Only Tile in your example is the same size as Object, so only that could share the same memory (but it shouldn't). None of the other types can be placed in the objects memory because they are longer. You need separate pools for each type.
Second, there should be no bearing of the object ID on how things are stored. There cannot be, once you take the first point into consideration, if the IDs are shared and the memory is not. But it must be pointed out explicitly - the position in a memory block is largely arbitrary and the IDs are not.
Why? Let's say you take object 40, "delete" it, then create a new object 40. Now let's say some buggy part of the program referenced the original ID 40. It goes looking for the original 40, which should error, but instead finds the new 40. You just created an entirely untrackable error. While this can happen with pointers, it is far more likely to happen with IDs, because few systems impose checks on ID usage. A main reason for indirecting access with IDs is to make access safer by making it easy to catch bad usage, so by making IDs reusable, you make them just as unsafe as storing pointers.
The actual model for handling this should look like how the operating system does similar operations (see below the divide for more on that...). That is to say, follow a model like this:
Create some sort of array (like a vector) of the type you want to store - the actual type, not pointers to it. Not Object, which is a generic base, but something like Player.
Size that to the size you expect to need.
Create a stack of size_t (for indexes) and push into it every index in the array. If you created 10 objects, you push 0 1 2 3 4 5 6 7 8 9.
Every time you need an object, pop an index from the stack and use the memory in that cell of the array.
If you run out of indexes, increase the size of the vector and push the newly created indexes.
When you use objects, indirect via the index that was popped.
Essentially, you need a class to manage the memory.
An alternative model would be to directly push pointers into a stack with matching pointer type. There are benefits to that, but it is also harder to debug. The primary benefit to that system is that it can easily be integrated into existing systems; however, most compilers do similar already...
That said, I suggest against this. It seems like a good idea on paper, and on very limited systems it is, but modern operating systems are not "limited systems" by that definition. Virtual memory already resolves the biggest reason to do this, memory fragmentation (which you did not mention). Many compiler allocators will attempt to more or less do what you are trying to do here in the standard library containers by drawing from memory pools, and those are far more manageable to use.
I once implemented a system just like this, but for many good reasons have ditched it in favor of a collection of unordered maps of pointers. I have plans to replace allocators if I discover performance or memory problems associated with this model. This lets me offset the concern of managing memory until testing/optimization, and doesn't require quirky system design at every level to handle abstraction.
When I say "quirky", believe me when I say that there are many more annoyances with the indirection-pool-stack design than I have listed.
See this example.
an University class has a Director and many student So my class will be like this
a)
class University {
Director d;
Student list[1000];
};
or
b)
class University {
Director* d;
Student* list[1000];
};
My problem is how to decide whether class attributes should be pointer or value.
Most all other answers focus on the detail of heap vs. direct containment (or provide no information at all, like use pointers when you want pointers... Rather than focusing on the details, consider the overall design of the application.
The first question would be about ownership. In your program, are those students and director owned by the class? Or do they exist outside of the class scope. In most simple applications, the objects might only exist inside the class, but in other more complex designs, the students might belong to the school, and only be referenced in the class (or the director might also teach some courses to other classes). If the class owns the objects, the composition will be the best approach: hold the director directly as a member, and the students inside a container that is directly held by the class (I would recommend a vector, which is the safe choice for most cases).
If the objects don't belong to the class, then you will rather use aggregation. Whoever owns the object will have to manage the lifetimes and decide how to store the real objects and the class would only hold references (in the general sense) to those objects. Things get more complicated as there are more choices. If ownership can be transferred, then you would dynamically allocate the objects and hold pointers, where you should read smart pointers so that memory will be managed for you.
If ownership does not change and the lifetime of the students/director are guaranteed to extend beyond the lifetime of the class, you could use references. In particular for the director. In the case of the students, it will be more complex as you cannot have containers of plain references, so the solution might still be pointers there, a vector of pointers. Another issue with references is that they cannot be reseated, which means that if you hold a reference to the director, the director of the class will be fixed for the whole lifetime of the class and you won't be able to replace her.
Design is somehow complicated and you will learn with experience, but hopefully this will provide a quick start onto your problem.
The issue here is: Where is the storage for these member variables? Sometimes it makes sense that a piece of data was allocated somewhere else and used other places. In that case a pointer may make sense (rather than using a copy constructor). However, usually that isn't the case (especially with encapsulation). Then you want to store the member data in the class. In such a case, and your example looks like it is, you don't want to use a pointer.
how to decide whether class attributes should be pointer or value
I would mostly go for value (i.e. object). In some special cases, I will choose a pointer (may be a smart one!). For your case, below would suffice:
class University {
Director d;
std::vector<Student> list;
public:
University () { list.reserve(1000); }
};
The advantage of having an object is that you don't have to do your own garbage collection as the resource management will be automatic.
Pointers can be used, when you want to change the ownership of the resource (similar to shallow copy), at the same time avoiding expensive copies created during copy c-tor or assignment. In all other cases, use objects (i.e. value) for composition.
Well it depends. Pointers should be used when you want to add stuff to the heap, while this means you have a bit more freedom in when/how you allocate memory, you have to add more code to avoid memory leaks: ie destructors and deleting stuff. It also allows you to easily modify the values from other functions/classes without having to pass a reference, just pass it in its pointer form.
One obvious situation when pointers are totally needed is in a binary tree node object, since it must contain objects of the same type as itself, it must use pointers to those objects. IE:
struct Node{
Node* left;
Node* right;
//Other stuff
};
In many situations however, its up to your own discretion. Just be responsible for your pointers if you use them.
Actually there are three options
1. Object
2. Reference
3. Pointer
It's part of the design/architect .. on what to use for what object.
Mostly .. the deciding criteria will be, lifecycles of the objects and the containers.
In both cases the class attributes are being stored by value, it just happens that in the second case those values are pointers.
Use pointers when you want pointers, use non-pointers when you don't want pointers. This entirely depends on the desired semantics of the class that you are writing.
This is what i would go for:
class University {
Director d;
Student **list;
};
Even though its much of a personal matter. i think using pointer to pointer is better in this case if you know what you are playing with!
I dont think a pointer array is a good choice. If you dont want pointers then use Value
I am new to C++ but I have some basic memory allocation knowledge in C. I am writing a class Card, which stores the card number and a list of class Activity object.
class Card {
public:
Card();
~Card();
vector<Activity> activities;
int cardNo;
}
Currently, I initialize the Activity object using code like:
Activity a = Activity("a");
and push them to the vector defined in the Card object.
But I found people tend to initialize using Activity *a = new Activity("a") instead (dynamically allocation?), and the objects declared in the former way (statically allocated?) will be freed when the function declares them terminated.
Then, if I initialize Activity objects the same way I did before, but initialize Card using the "new Card()" way, is it possible that the Activity objects may have been de-allocated before Card object freed? Should I switch to use "new Activity()" to initialize objects stored in Card?
No, what you're doing is fine. When you push an object onto a vector, a copy is made. So when your function returns, your a is destroyed, but the vector you added it to still has its own seperate copy.
One reason someone might allocate an instance of a class dynamically and push it onto a vector would be that copying objects of that particular class around is expensive (and vector does a lot of copying around internally) and they want to avoid that, so they store pointers instead of objects so that only copies of the pointers are made, not of the objects (which is would not be nearly so expensive). That all depends on the class though; generally you can use vectors of objects without any performance issues.
Note: a shortcut1 for Activity a = Activity("a"); is Activity a("a"), or better, do what Benjamin suggested and do activites.push_back(Activity("a")) if you're not performing some operations on the Activity before you push it.
1 It's not really a shortcut because it does something different, but for your intents and purposes, it is.
"But I found people tend to initialize using Activity *a = new
Activity("a") instead (dynamically allocation?)"
What people? They're doing it wrong. You're doing it right, sort of. You could just do this instead:
activities.push_back(Activity("a"));
A few cases where you need pointers:
it might be NULL instead of some dummy state
it is polymorphic
shared, not exclusive to the class
there is a circular dependency or recursion that prevents a direct member variable
In this particular case, as with most STL containers, member variables are preferred over member pointers.
I have two lines of code I want explained a bit please. As much as you can tell me. Mainly the benefits of each and what is happening behind the scenes with memory and such.
Here are two structs as an example:
struct Employee
{
std::string firstname, lastname;
char middleInitial;
Date hiringDate; // another struct, not important for example
short department;
};
struct Manager
{
Employee emp; // manager employee record
list<Employee*>group; // people managed
};
Which is better to use out of these two in the above struct and why?
list<Employee*>group;
list<Employee>group;
First of all, std::list is a doubly-linked list. So both those statements are creating a linked list of employees.
list<Employee*> group;
This creates a list of pointers to Employee objects. In this case there needs to be some other code to allocate each employee before you can add it to the list. Similarly, each employee must be deleted separately, std::list will not do this for you. If the list of employees is to be shared with some other entity this would make sense. It'd probably be better to place the employee in a smart pointer class to prevent memory leaks. Something like
typedef std::list<std::shared_ptr<Employee>> EmployeeList;
EmployeeList group;
This line
list<Employee>group;
creates a list of Employee objects by value. Here you can construct Employee objects on the stack, add them to the list and not have to worry about memory allocation. This makes sense if the employee list is not shared with anything else.
One is a list of pointers and the other is a list of objects. If you've already allocated the objects, the first makes sense.
You probably want to use the second one, if you store the "people managed" to be persisted also in another location. To elaborate: if you also have a global list of companyEmployees you probably want to have pointers, as you want to share the object representing an employee between the locations (so that, for example, if you update the name the change is "seen" from both locations).
If instead you only want to know "why a list of structs instead of a list of pointers" the answer is: better memory locality, no need to de-allocate the single Employee objects, but careful that every assignement to/from a list node (for example, through an iterator and its * operator) copies the whole struct and not just a pointer.
The first one stores the objects by pointer. In this case you need to carefully document who owns the allocated memory and who's responsible for cleaning it up when done. The second one stores the objects by value and has full control of their lifespan.
Which one to use depends on context you haven't given in your question although I favor the second slightly as a default because it doesn't leave open the possibility of mismanaging your memory.
But after all that, carefully consider if list is actually the right container choice for you. Typically it's a low-priority container that satisfies very specific needs. I almost always favor vector and deque first for random access containers, or set and map for ordered containers.
If you do need to store pointers in the container, boost provides ptr-container classes that manage the memory for you, or I suggest storing some sort of smart pointer so that the memory is cleaned up automatically when the object isn't needed anymore.
A lot depends on what you are doing. For starters, do you really want
Manager to contain an Employee, rather than to be one: the classical
example of a manager (one of the classic OO examples) would be:
struct Manager : public Employee
{
list<Employee*> group;
};
Otherwise, you have the problem that you cannot put managers into the
group of another manager; you're limited to one level in the management
hierarchy.
The second point is that in order to make an intelligent decision, you
have to understand the role of Employee in the program. If Employee
is just a value: some hard data, typically immutable (except by
assignment of a complete Employee), then list<Employee> group is
definitely to be preferred: don't use pointers unless you have to. If
Employee is a "entity", which models some external entity (say an
employee of the firm), you would generally make it uncopyable and
unassignable, and use list<Employee*> (with some sort of mechanism to
inform the Manager when the employee is fired, and the pointed to
object is deleted). If managers are employees, and you don't want to
loose this fact when they are added to a group, then you have to use the
pointer version: polymorphism requires pointers or references to work
(and you can't have a container of references).
The two lists are good, but they will require a completely different handling.
list<Employee*>group;
is a list of pointers to objects of type Employee and you will store there pointers to objects allocated dynamically, and you will need to be particularly clear as to who will delete those objects.
list<Employee>group;
is a list of objects of type Employee; you get the benefit (and associated cost in terms of performance) of dealing with concrete instances that you do not need to memory manage yourself.
Specifically, one of the advantages of using std::list compared to a plain array, is that you can have a list of objects and avoid the cost and risks of dealing with dynamic memory allocation and pointers.
With a list of objects, you can do, e. g.
Employee a; // object allocated in the stack
list.push_back(a); // the list does a copy for you
Employee* b = new Employee....
list.push_back(*b); // the object pointed is copied
delete b;
With a list of pointers you are forced at using always dynamic allocation, in practice, or refer to object whose lifetime is longer than the list's (if you can guarantee it).
By using a std::list of pointers, you are more or less in the same situation as when using a plain array of pointers as far as memory management is concerned. The only advantage you get is that the list can grow dynamically without effort on your part.
I personally don't see much sense in using a list of pointers; basically, because I think that pointers should be used (always, when possible) through smart pointers. So, if you really need pointers, you will be better off, IMO, using a list of smart pointers provided by boost.
Use the first one if you're allocating or accessing the structures separately.
Use the second one if you'll only be allocating/accessing them through the list.
First one defines a list of pointers to objects, the second a list of objects.
The first version (with pointers) is preferred by most of the programmers.
The main reason is that STL is copying elements by value making sorting and internal reallocation more efficient.
You probably want to use unique_ptr<> or auto_ptr<> or shared_ptr<> rather then plain old * pointers. This goes some if not the whole way of having both the expected use without much of the memory issues with using non-heap objects...