I have a vector of journeys and a vector of locations. A journey is between two places.
struct Data {
std::vector<Journey> m_journeys;
std::vector<Locations> m_locations;
};
struct Journey {
?? m_startLocation;
?? m_endLocation;
};
How can I create the relationship between each journey and two locations?
I thought I could just store references/pointers to the start and end locations, however if more locations are added to the vector, then it will reallocate storage and move all the locations elsewhere in memory, and then the pointers to the locations will point to junk.
I could store the place names and then search the list in Data, but that would require keeping a reference to Data (breaking encapsulation/SRP), and then a not so efficient search.
I think if all the objects were created on the heap, then shared_ptr could be used, (so Data would contain std::vector<std::shared_ptr<Journey>>), then this would work? (it would require massive rewrite so avoiding this would be preferable)
Is there some C++/STL feature that is like a pointer but abstracts away/is independent of memory location (or order in the vector)?
No, there isn't any "C++/STL feature that is like a pointer but abstracts away/is independent of memory location".
That answers that.
This is simply not the right set of containers for such a relationship between classes. You have to pick the appropriate container for your objects first, instead of selecting some arbitrary container first, and then trying to figure out how to make it work with your relationship.
Using a vector of std::shared_ptrs would be one option, just need to watch out for circular references. Another option would be to use std::list instead of std::vector, since std::list does not reallocate when it grows.
If each Locations instance has a unique identifier of some kind, using a std::map, and then using that location identifier to refer to a location, and then looking it up in the map. Although a std::map also doesn't reallocate upon growth, the layer of indirection offers some value as well.
I'd say make a vector<shared_ptr<Location>>for your index of locations, and Journey would contain two weak_ptr<Location>.
struct Data {
std::vector<Journey> m_journeys;
std::vector<std::shared_ptr<Location>> m_locations;
};
struct Journey {
std::weak_ptr<Location> m_startLocation;
std::weak_ptr<Location> m_endLocation;
};
std::weak_ptr can dangle and that's exactly what you want. :)
The concern is that one could access a Journey containing a deleted Location. A weak pointer provides an expired() method that can tell you if the data of the parent shared pointer (that would be in your m_locations vector) still exists.
Accessing data from a weak pointer is safe, and will require the use of the lock() method.
Here is a great example of how one usually uses a weak pointer:
http://en.cppreference.com/w/cpp/memory/weak_ptr/lock
Related
I have a conainter, lets say a std::list<int>, which I would like to share between objects. One of the objects is known to live longer than the others, so he will hold the container. In order to be able to access the list, the other objects may have a pointer to the list.
Since the holder object might get moved, I'll need to wrap the list with a unique_ptr:
class LongLiveHolder { std::unique_ptr<std::list<int>> list; };
class ShortLiveObject { std::list<int>& list; };
However, I don't really need the unique_ptr wrapper. Since the list probably just contains a [unique_ptr] pointer to the first node (and a pointer to the last node), I could, theoretically, have those pointers at the other objects:
class LongLiveHolder { std::unique_ptr<NonExistentListNode<int>> back; };
class ShortLiveObject { NonExistentListNode<int>& back; };
, which would save me a redundant dereference when accessing the list, except that I would no longer have the full std::list interface to use with the shorter-lived object- just the node pointers.
Can I somehow get rid of this extra layer of indirection, while still having the std::list interface in the shorter-lived object?
Preface
You may be overthinking the cost of the extra indirection from the std::unique_ptr (unless you have a lot of these lists and you know that usages of them will be frequent and intermixed with other procedures). In general, I'd first trust my compiler to do smart things. If you want to know the cost, do performance profiling.
The main purpose of the std::unique_ptr in your use-case is just to have shared data with a stable address when other data that reference it gets moved. If you use the list member of the long-lived object multiple times in a single procedure, you can possibly help your compiler to help you (and also get some nicer-to-read code) when you use the list through the long-lived object by making a variable in the scope of the procedure that stores a reference to the std::list pointed to by the std::unique_ptr like:
void fn(LongLiveHolder& holder) {
auto& list {holder.list.get()};
list.<some_operation_1>(...);
list.<some_operation_2>(...);
list.<some_operation_3>(...);
}
But again, you should inspect the generated machine code and do performance profiling if you really want to know what kind of difference it makes.
If Context Permits, Write your own List
You said:
However, I don't really need the unique_ptr wrapper. Since the list probably just contains a [unique_ptr] pointer to the first node (and a pointer to the last node), I could, theoretically, have those pointers at the other objects: [...]
Considering Changes in what is the First Node
What if the first node of the list is allowed to be deleted? What if a new node is allowed to be inserted at the beginning of the list? You'd need a very specific context for those to not be requirements. What you want in your short-lived object is a view abstractions which supports the same interface as the actual list but just doesn't manage the lifetime of the list contents. If you implement the view abstraction as a pointer to the list's first node, then how will the view object know about changes to what the "real"/lifetime-managing list considers to be the first node? It can't- unless the lifetime-managing list keeps an internal list of all views of itself which are alive and also updates those (which itself is a performance and space overhead), and even then, what about the reverse? If the view abstraction was used to change what's considered the first node, how would the lifetime-managing list know about that change? The simplest, sane solution is to have an extra level of indirection: make the view point to the list instead of to what was the list's first node when the view was created.
Considering Requirements on Time Complexity of getting the list size
I'm pretty sure a std::list can't just hold pointers to front and back nodes. For one thing, since c++11 requires that std::list::size() is O(1), std::list probably has to keep track of its size at all times in a counter member- either storing it in itself, or doing some kind of size-tracking in each node struct, or some other implementation-defined behaviour. I'm pretty sure the simplest and most performant way to have multiple moveable references (non-const pointers) to something that needs to do this kind of bookkeeping is to just add another level of indirection.
You could try to "skip" the indirection layer required by the bookkeeping for specific cases that don't require that information, which is the iterators/node-pointers approach, which I'll comment on later. I can't think of a better place or way to store that bookkeeping other than with the collection itself. Ie. If the list interface has requirements that require such bookkeeping, an extra layer of indirection for each user of the list implementation has a very strong design rationale.
If Context Permits
If you don't care about having O(1) to get the size of your list, and you know that what is considered the first node will not change for the lifetime of the short-lived object, then you can write your own List class list-view class and make your own context-specific optimizations. That's one of the big selling-points of languages like C++: You get a nice standard library that does commonly useful things, and when you have a specific scenario where some features of those tools aren't required and are resulting in unnecessary overhead, you can build your own tool/abstraction (or possibly use someone else's library).
Commentary on std::unique_ptr + reference
Your first snippet works, but you can probably get some better implicit constructors and such for SortLiveObject by using std::reference_wrapper, since the default implicity-declared copy-assignment and default-construct functions get deleted when there's a reference member.
class LongLiveHolder { std::unique_ptr<std::list<int>> list; };
class ShortLiveObject { std::reference_wrapper<std::list<int>> list; };
Commentary on std::shared_ptr + std::weak_ref
Like #Adrian Maire suggested, std::shared_ptr in the longer-lived, object which might move while the shorter-lived object exists, and std::weak_ptr in the shorter-lived object is a working approach, but it probably has more overhead (at least coming from the ref-count) than using std::unique_ptr + a reference, and I can't think of any generalized pros, so I wouldn't suggest it unless you already had some other reason to use a std::shared_ptr. In the scenario you gave, I'm pretty sure you do not.
Commentary on Storing iterators/node-pointers in the short-lived object
#Daniel Langr already commented about this, but I'll try to expand.
Specifically for std::list, there is a possible standard-compliant solution (with several caveats) that doesn't have the extra indirection of the smart pointer. Caveats:
You must be okay with only having an iterator interface for the shorter-lived object (which you indicated that you are not).
The front and back iterators must be stable for the lifetime of the shorter-lived object. (the iterators should not be deleted from the list, and the shorter-lived object won't see new list entries that are pushed to the front or back by someone using the longer-lived object).
From cppreference.com's page for std::list's constructors:
After container move construction (overload (8)), references, pointers, and iterators (other than the end iterator) to other remain valid, but refer to elements that are now in *this. The current standard makes this guarantee via the blanket statement in [container.requirements.general]/12, and a more direct guarantee is under consideration via LWG 2321.
From cppreference.com's page for std::list:
Adding, removing and moving the elements within the list or across several lists does not invalidate the iterators or references. An iterator is invalidated only when the corresponding element is deleted.
But I am not a language lawyer. I could be missing something important.
Also, you replied to Daniel saying:
Some iterators get invalid when moving the container (e.g. insert_iterator) #DanielLangr
Yes, so if you want to be able to make std::input_iterators, use the std::unique_ptr + reference approach and construct short-lived std::input_iterators when needed instead of trying to store long-lived ones.
If the list owner will be moved, then you need some memory address to share somehow.
You already indicated the unique_ptr. It's a decent solution if the non-owners don't need to save it internally.
The std::shared_ptr is an obvious alternative.
Finally, you can have a std::shared_ptr in the owner object, and pass std::weak_ptr to non-owners.
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 have been given some code to read which does some geometric operations on meshes.
A mesh data structure, by definition, should contain at least the information
regarding the coordinates of points, edge connectivity and face information.
So, the code given to me has classes to define vertex, edge and face data structure,
named respectively as Vertex, Edge and Face.
However the mesh class looks like this.
class basemesh
{
public:
/* Methods to operate on the protected data below.*/
protected:
/*! list of edges */
std::list<Edge*> m_edges;
/*! list of vertices */
std::list<Vertex*> m_verts;
/*! list of faces */
std::list<Face*> m_faces;
}
My question: Why does the mesh data structure store a list of pointers rather than a
list of the corresponding objects themselves.
e.g why not say directly std::list<Vertex>
I have seen this construct being used in a couple of other C++ codes
Does this have something to do with inheritance of classes? Or is it something to do
with performance with regards to iterating on the list?
This basemesh class is, as the name suggests, a base class from which
other specialized meshes are derived.
There is no performance reasons here. Its simply a case of ownership sharing. Remember this as a rule of thumb: Pointers in C++ are used to share/pass ownership of a resource, or to provide polymorphic behaviour through dynamic binding.
People is talking about performence because you avoid copying the things. Blah, blah, blah.
If you need to copy, you should copy. The only reason why its using pointers is because the author didn't want to copy the things when he/she copies the list of things, in other words, he/she wants to maintain the same things in two locations (lists): Ownership sharing, as I said before.
On the other hand, note that the class is called basemesh. So the real point of the pointers here could be to work with polymorphic vertices, edges, etc (Dynamic binding).
NOTE: If performance was the point here, I'm pretty sure the author would be using compact and aligned non-cache-miss-prone std::vector instead of std::list. In this case, the most presumable reason about the use of pointers is polymorphism, not performance. Anything related to pointers, dereferencing, and transversing linked lists will always have less performance than compact data, exactly what std::vector<Vertex> is, for example. Again, if the use of pointers is not for polymorphism, is for ownership related things, not performance.
Other note: Copying Yes, you are copying. But note what and how are copying. Vertices are, except of a very rare implementation, pairs of floats/ints. There is no gain at all about copying 64bits of floats vs 32/64bits of pointers.
Also note that, except you don't be so lucky, you are copying things stored at the same cache line, or almost at the cache.
A good rule about optimization nowadays is: Try to optimize memory accesses, not CPU cicles. I recommend this thread: What is "cache-friendly" code?, and this for a practical case: Why are elementwise additions much faster in separate loops than in a combined loop?. Finally, this thread contains good notes about optimizing using modern compilers.
My guess is that it's either made for a very unusual specific case, but more likely, it's written by a programmer who doesn't know how heap allocations or std::list actually work, and just blindly use pointers.
It seems very unlikely a std::list of pointers to single vertices was the best option performance- or designwise.
On a practical level if a method changes a point it does not need to reproduce the change in the other data structures. They will all point to the same thing.
But in terms of memory management it would be wise to use smart pointers,
At a guess I'd say it's so that these objects can have pointers to each other (e.g. an Edge can have pointers to two Vertices, each of which can have a pointer back to the Edge).
If all the Vertices lived in a std::list in basemesh, then pointers to them would not be reliable, although list::iterators might work well enough.
Using pointers is less efficient when retrieving inner data in general because you will have to dereference the value every time you access it.
But at the same time it will be more efficient when passing data around, since you are just passing pointers. I guess the solution chosen is related to the fact that data is shared between multiple objects by composition. Eg: multiple Edge instances could refer to same Vertex.
Now std::list guarantees that addresses to values contained are consistent until the element itself is removed so actually doing something like
Edge(const Vertex *v1, const Vertex *v2) { .. }
std::list<Vertex>::iterator it = std::advance(vertices.begin(), 3);
std::list<Vertex>::iterator it2 = std::advance(vertices.begin(), 5);
new Edge(&(*it), &(*it2));
Would work since addresses won't be invalidated so there is no real necessity to use pointers to store objects. Actually by using this solution you don't need to care about memory management of single objects since you won't need to delete them or wrap them into smart pointers.
It's using pointers for performance reasons and to reduce the chance of an error.
Imagine the alternative of not using pointers. Every insertion into class basemesh would cause a copy of the object to be created, and every time you access an object, if you aren't careful, you'll get a copy as well.
For example, imagine this statement:
Edge e = m_edges[0];
e.doSomethingThatModifiesState();
In this example, without pointers, you'll have a copy of the object, and any operations you perform on it will not affect the actual edge object stored in m_edges.
With pointers, you don't have this issue:
Edge* e = m_edges[0];
e->doSomethingThatModifiesState();
In this example, no copy of the object is made, and when you do something, you get the intended behavior.
As many others said the speed is the most obvious reason. Another reason is to get polymorphic behavior through pointers to the base class.
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...
I just started learning about pointers in C++, and I'm not very sure on when to use pointers, and when to use actual objects.
For example, in one of my assignments we have to construct a gPolyline class, where each point is defined by a gVector. Right now my variables for the gPolyline class looks like this:
private:
vector<gVector3*> points;
If I had vector< gVector3 > points instead, what difference would it make? Also, is there a general rule of thumb for when to use pointers? Thanks in advance!
The general rule of thumb is to use pointers when you need to, and values or references when you can.
If you use vector<gVector3> inserting elements will make copies of these elements and the elements will not be connected any more to the item you inserted. When you store pointers, the vector just refers to the object you inserted.
So if you want several vectors to share the same elements, so that changes in the element are reflected in all the vectors, you need the vectors to contain pointers. If you don't need such functionality storing values is usually better, for example it saves you from worrying about when to delete all these pointed to objects.
Pointers are generally to be avoided in modern C++. The primary purpose for pointers nowadays revolves around the fact that pointers can be polymorphic, whereas explicit objects are not.
When you need polymorphism nowadays though it's better to use a smart pointer class -- such as std::shared_ptr (if your compiler supports C++0x extensions), std::tr1::shared_ptr (if your compiler doesn't support C++0x but does support TR1) or boost::shared_ptr.
Generally, it's a good idea to use pointers when you have to, but references or alternatively objects objects (think of values) when you can.
First you need to know if gVector3 fulfils requirements of standard containers, namely if the type gVector3 copyable and assignable. It is useful if gVector3 is default constructible as well (see UPDATE note below).
Assuming it does, then you have two choices, store objects of gVector3 directly in std::vector
std::vector<gVector3> points;
points.push_back(gVector(1, 2, 3)); // std::vector will make a copy of passed object
or manage creation (and also destruction) of gVector3 objects manually.
std::vector points;
points.push_back(new gVector3(1, 2, 3));
//...
When the points array is no longer needed, remember to talk through all elements and call delete operator on it.
Now, it's your choice if you can manipulate gVector3 as objects (you can assume to think of them as values or value objects) because (if, see condition above) thanks to availability of copy constructor and assignment operator the following operations are possible:
gVector3 v1(1, 2, 3);
gVector3 v2;
v2 = v1; // assignment
gVector3 v3(v2); // copy construction
or you may want or need to allocate objects of gVector3 in dynamic storage using new operator. Meaning, you may want or need to manage lifetime of those objects on your own.
By the way, you may be also wondering When should I use references, and when should I use pointers?
UPDATE: Here is explanation to the note on default constructibility. Thanks to Neil for pointing that it was initially unclear. As Neil correctly noticed, it is not required by C++ standard, however I pointed on this feature because it is an important and useful one. If type T is not default constructible, what is not required by the C++ standard, then user should be aware of potential problems which I try to illustrate below:
#include <vector>
struct T
{
int i;
T(int i) : i(i) {}
};
int main()
{
// Request vector of 10 elements
std::vector<T> v(10); // Compilation error about missing T::T() function/ctor
}
You can use pointers or objects - it's really the same at the end of the day.
If you have a pointer, you'll need to allocate space for the actual object (then point to it) any way. At the end of the day, if you have a million objects regardless of whether you are storing pointers or the objects themselves, you'll have the space for a million objects allocated in the memory.
When to use pointers instead? If you need to pass the objects themselves around, modify individual elements after they are in the data structure without having to retrieve them each and every time, or if you're using a custom memory manager to manage the allocation, deallocation, and cleanup of the objects.
Putting the objects themselves in the STL structure is easier and simpler. It requires less * and -> operators which you may find to be difficult to comprehend. Certain STL objects would need to have the objects themselves present instead of pointers in their default format (i.e. hashtables that need to hash the entry - and you want to hash the object, not the pointer to it) but you can always work around that by overriding functions, etc.
Bottom line: use pointers when it makes sense to. Use objects otherwise.
Normally you use objects.
Its easier to eat an apple than an apple on a stick (OK 2 meter stick because I like candy apples).
In this case just make it a vector<gVector3>
If you had a vector<g3Vector*> this implies that you are dynamically allocating new objects of g3Vector (using the new operator). If so then you need to call delete on these pointers at some point and std::Vector is not designed to do that.
But every rule is an exception.
If g3Vector is a huge object that costs a lot to copy (hard to tell read your documentation) then it may be more effecient to store as a pointer. But in this case I would use the boost::ptr_vector<g3Vector> as this automatically manages the life span of the object.