Is it posible to declare a global array of a struct, and add elements dynamically to it?
Thanks.
If you want to dynamically add elements to something, you might consider using a list. You could create a global list, and dynamically add elements to it as needed. If you really need array type functionality, a vector might be more your speed. In this case, the STL is likely to provide what you need.
It's also good to note that globals aren't always a good idea. If you're using globals a lot, you may want to consider refactoring your code so they won't be necessary. Many people consider global variables to be a code smell.
Avoid using non-PODs as globals. However, you can do this:
std::vector<YourStruct>& global_list()
{
static std::vector<YourStruct> v;
return v;
}
This at least avoids global initialization order problems by enforcing a policy where access is initialization. Otherwise you'll very easily wander into undefined behavior land.
As for what variable-sized container to use, it's hard to tell without more contextual information. Do you need to be able to quickly search for elements in the list, for example? Will you be removing elements from the middle of the list frequently? Do you need random-access, or is sequential iteration fine? Etc. etc.
See std::vector.
Any time you're tempted to use an array, you'd probably do better to use a vector, list, or one of the many other STL containers.
No, not directly. But you may use a STL or self-made vector.
You can use a STL container. Alternatively you can declare of your type and allocate/deallocate memory by yourself. But you should not use the 2nd way.
Related
I have a huge program (VS project) which contains global variable. It modifies from hundreds places. Actually it standard STL container (std::vector) and question is how can I track down this particular variable modifications?
In my work I use VS debugger (Prof 2017 15.9.5)
There are a few solutions which come to my mind:
Create another class which will encapsulte this vector.
Then allow users to use this vector by adding getter returning
reference to it.
Then you can put a breakpoint in getter.
Put a memory breakpoint on one of vector's members but it is plantform specific solution which may not work in all scenarios.
Replace std::vector with your custom type with interface identical to std::vector's which would use original std::vector in its internals.
With this solution you can monitor accesses more precisely.
P.S. remove this global ASAP.
I have a set of small objects. Each of these objects points to other objects. These pointers might be realized as actual pointers or as index into an array of the objects or something else. It might be an array of such pointers whose length might change. There might be pointers to objects of the same type and to other types, but this is known at compile time.
So, for example: I have a class Person. This person has two pointers to its parent Persons. There's another class Place. Each Person has a list of pointers to all Places he/she has visited.
In contrast to an actual family tree, I might want to change the tree from time to time by deleting/inserting some Persons.
Is there a container in the C++ Standard Library (C++ 11) for that purpose or should I better look for a dedicated memory management class?
I will have to pass the data to a C interface why I would prefer a storage method which is based on an accessible (read only) linear array.
Sounds like a great time to quote Stepanov:
Use vectors whenever you can. If you cannot use vectors, redesign your solution so that you can use vectors.
The "accessible linear array" part points to vector<Person> - none of the other containers have that feature - and the rest of your use-case doesn't suggest any specific kind storage or access. Part of it sounds like it might be cleaner if you could do vector<shared_ptr<Person>> but that would break your C interface requirement. So vector<Person> is probably your answer.
Questions:
"There might be pointers to objects of the same type and to other types, but this is known at compile time."
"These pointers might be realized as actual pointers or as index into an array of the objects or something else."
In contrast to an actual family tree, I might want to change the tree from time to time by deleting/inserting some Persons.
"Is there a container in the C++ Standard Library (C++ 11) for that purpose or should I better look for a dedicated memory management class?"
"I will have to pass the data to a C interface why I would prefer a storage method which is based on an accessible (read only) linear array."
Answers:
This could become difficult if you want to use pointers to multiple types of objects in a single container. But you could make either a raw array or a std::vector work.
If you're just using indices that would greatly simplify your "pointers to multiple types" problem. Again either a raw array or a std::vector work.
Dynamically changing raw array sizes gets sketchy fast, I'd say this is a point for std::vector.
Depending upon the time that you are willing to put in, managing your memory is a tremendous endeavor, I'd stick with a raw array or std::vector until they pried my cold dead fingers loose.
If you have C++11 using std::vector::data can make a std::vector just as usable as a raw array here, if not this would be simpler to implement as a raw array.
std::vector has numerous benefits to you as the programmer. Not the least of which is automatic memory management. So I'd lean toward std::vector where it is an option.
I prefer to use vector rather than other (list, etc) . as Bjarne said "If you know int and vector, so you know C++".
Here is the link at Youtube, as Bjarne said about vector:
Bjarne Stroustrup: Why you should avoid Linked Lists
I'd like to use a std::vector to control a given piece of memory. First of all I'm pretty sure this isn't good practice, but curiosity has the better of me and I'd like to know how to do this anyway.
The problem I have is a method like this:
vector<float> getRow(unsigned long rowIndex)
{
float* row = _m->getRow(rowIndex); // row is now a piece of memory (of a known size) that I control
vector<float> returnValue(row, row+_m->cols()); // construct a new vec from this data
delete [] row; // delete the original memory
return returnValue; // return the new vector
}
_m is a DLL interface class which returns an array of float which is the callers responsibility to delete. So I'd like to wrap this in a vector and return that to the user.... but this implementation allocates new memory for the vector, copies it, and then deletes the returned memory, then returns the vector.
What I'd like to do is to straight up tell the new vector that it has full control over this block of memory so when it gets deleted that memory gets cleaned up.
UPDATE: The original motivation for this (memory returned from a DLL) has been fairly firmly squashed by a number of responders :) However, I'd love to know the answer to the question anyway... Is there a way to construct a std::vector using a given chunk of pre-allocated memory T* array, and the size of this memory?
The obvious answer is to use a custom allocator, however you might find that is really quite a heavyweight solution for what you need. If you want to do it, the simplest way is to take the allocator defined (as the default scond template argument to vector<>) by the implementation, copy that and make it work as required.
Another solution might be to define a template specialisation of vector, define as much of the interface as you actually need and implement the memory customisation.
Finally, how about defining your own container with a conforming STL interface, defining random access iterators etc. This might be quite easy given that underlying array will map nicely to vector<>, and pointers into it will map to iterators.
Comment on UPDATE: "Is there a way to construct a std::vector using a given chunk of pre-allocated memory T* array, and the size of this memory?"
Surely the simple answer here is "No". Provided you want the result to be a vector<>, then it has to support growing as required, such as through the reserve() method, and that will not be possible for a given fixed allocation. So the real question is really: what exactly do you want to achieve? Something that can be used like vector<>, or something that really does have to in some sense be a vector, and if so, what is that sense?
Vector's default allocator doesn't provide this type of access to its internals. You could do it with your own allocator (vector's second template parameter), but that would change the type of the vector.
It would be much easier if you could write directly into the vector:
vector<float> getRow(unsigned long rowIndex) {
vector<float> row (_m->cols());
_m->getRow(rowIndex, &row[0]); // writes _m->cols() values into &row[0]
return row;
}
Note that &row[0] is a float* and it is guaranteed for vector to store items contiguously.
The most important thing to know here is that different DLL/Modules have different Heaps. This means that any memory that is allocated from a DLL needs to be deleted from that DLL (it's not just a matter of compiler version or delete vs delete[] or whatever). DO NOT PASS MEMORY MANAGEMENT RESPONSIBILITY ACROSS A DLL BOUNDARY. This includes creating a std::vector in a dll and returning it. But it also includes passing a std::vector to the DLL to be filled by the DLL; such an operation is unsafe since you don't know for sure that the std::vector will not try a resize of some kind while it is being filled with values.
There are two options:
Define your own allocator for the std::vector class that uses an allocation function that is guaranteed to reside in the DLL/Module from which the vector was created. This can easily be done with dynamic binding (that is, make the allocator class call some virtual function). Since dynamic binding will look-up in the vtable for the function call, it is guaranteed that it will fall in the code from the DLL/Module that originally created it.
Don't pass the vector object to or from the DLL. You can use, for example, a function getRowBegin() and getRowEnd() that return iterators (i.e. pointers) in the row array (if it is contiguous), and let the user std::copy that into its own, local std::vector object. You could also do it the other way around, pass the iterators begin() and end() to a function like fillRowInto(begin, end).
This problem is very real, although many people neglect it without knowing. Don't underestimate it. I have personally suffered silent bugs related to this issue and it wasn't pretty! It took me months to resolve it.
I have checked in the source code, and boost::shared_ptr and boost::shared_array use dynamic binding (first option above) to deal with this.. however, they are not guaranteed to be binary compatible. Still, this could be a slightly better option (usually binary compatibility is a much lesser problem than memory management across modules).
Your best bet is probably a std::vector<shared_ptr<MatrixCelType>>.
Lots more details in this thread.
If you're trying to change where/how the vector allocates/reallocates/deallocates memory, the allocator template parameter of the vector class is what you're looking for.
If you're simply trying to avoid the overhead of construction, copy construction, assignment, and destruction, then allow the user to instantiate the vector, then pass it to your function by reference. The user is then responsible for construction and destruction.
It sounds like what you're looking for is a form of smart pointer. One that deletes what it points to when it's destroyed. Look into the Boost libraries or roll your own in that case.
The Boost.SmartPtr library contains a whole lot of interesting classes, some of which are dedicated to handle arrays.
For example, behold scoped_array:
int main(int argc, char* argv[])
{
boost::scoped_array<float> array(_m->getRow(atoi(argv[1])));
return 0;
}
The issue, of course, is that scoped_array cannot be copied, so if you really want a std::vector<float>, #Fred Nurk's is probably the best you can get.
In the ideal case you'd want the equivalent to unique_ptr but in array form, however I don't think it's part of the standard.
just came a across a situation where I needs to store heap-allocated pointers (to a class B) in an STL container. The class that owns the privately held container (class A) also creates the instances of B. Class A will be able to return a const pointers to B instances for clients of A.
Now, does it matter if these pointer are stored in a set or a vector? I thought of having a set just to verify that no duplicates are stored but since addresses are stored, two B pointers with the same data can be stored (unless I provide a comparison class for data comparison I presume).
Any thoughts on this (quite vague) subject? What are the pros/cons for the alternatives? Are smart_pointers something to look into?
Please ask me if anything imperative is unclear, thank you!
There's nothing wrong with storing pointers in a standard container - be it a vector, set, map, or whatever. You just have to be aware of who owns that memory and make sure that it's released appropriately. When choosing a container, choose the container that makes the most sense for your needs. vector is great for random access and appending but not so great for inserting elsewhere in the container. list deals with insertions extremely well, but it doesn't have random access. Sets ensure that there are no duplicates in the container and it's sorted (though the sorting isn't very useful if the set holds pointers and you don't give a comparator function) whereas a map is a set of key-value pairs, so sorting and access is done by key. Etc. Etc. Every container has its pros and cons and which is best for a particular situation depends entirely on that situation.
As for pointers, again, having pointers in containers is fine. The issue that you need to worry about is who owns the memory and therefore must worry about freeing it. If there is a clear object that owns what a particular pointer points to, then it should probably be that object which frees it. If it's essentially the container which owns the memory, then you need to make sure that you delete all of the pointers in the container before the container is destroyed.
If you are concerned with there being multiple pointers to the same data floating around or there is no clear owner for a particular chunk of memory, then smart pointers are a good solution. Boost's shared_ptr would probably be a good one to use, and shared_ptr will be part of C++0x. Many would suggest that you should always use shared pointers, but there is some overhead involved and whether it's best for your particular application will depend entirely on your application.
Ultimately, you need to be aware of the strengths and weaknesses of the various container types and determine what the best container is for whatever you're doing. The same goes for how to deal with pointer management. You need to write your program in a way that it's clear who owns a particular chunk of memory and make sure that that owner frees it when appropriate. Shared pointers are just one solution for that (albeit an excellent one). What the best solution is depends on the particulars of your program.
Why would there be any duplicates in the first place? If class A is the sole entity responsible for creating the instances, and it holds the container privately, meaning there's no way for others to mutate it, it seems to me that there should be no cause for duplicates. Well, if there is, won't that be remediable by some checking prior to adding the pointer to the vector?
I don't know why it would matter if you store a pointer in what kind of container. Containers don't really manipulate their data, they only provide access to them in different ways. So, it's up to you :)
If you need to store pointers in stl containers, use shared_ptr.
Now, the set sounds completely wrong. What are you going to do with those?
If you need to add and remove, then list.
If you need to iterate over range, or all, then vector.
If you need to access specific, knowing a key, then map.
Take a look at others as well. One size doesn't fit all.
My answer is that any decisions that you make have be be with your goal in mind. If you need a 'no duplicates allowed' rule that a set enforces, then use a set. If not then you might want to use a vector or any container might do the trick.
As for smart_pointers yes, they are really really useful. Should they be used? I don't know, once again I don't know what your end goal is or the problem that you are trying to solve with them.
Basically it comes down this. If I said "I want to use a hammer. What do you think of that?" you would probably say "Well what for, I know that hammers are pretty good for nails and wood scenarios but they could also be used as a tool to hurt people or maybe as a book stand. Look, just wait a second, what is this for again?" The problem is that I have not, really said why I want to use a hammer. I have not said what goal I am trying to achieve.
So if you have sort of an overall goal then why not let us know, then it will be obvious if you are using the right tools for the job and we can help you more.
In my opinion, stick with vector unless you have a real reason not to. Sets come with some runtime overhead as well as quite large semantic overhead compared to a vector.
I want to be able to have a vector of vectors of some type such as:
vector<vector<MyStruct> > vecOfVec;
I then create a vector of MyStruct, and populate it.
vector<MyStruct> someStructs;
// Populate it with data
Then finally add someStructs to vecOfVec;
vecOfVec.push_back(someStructs);
What I want to do is avoid having the copy constructor calls when pushing the vector. I know this can be accomplished by using a vector of pointers, but I'd like to avoid that if possible.
One strategy I've thought of seems to work, but I don't know if I'm over-engineering this problem.
// Push back an empty vector
vecOfVec.push_back(vector<MyStruct>());
// Swap the empty with the filled vector (constant time)
vecOfVec.back().swap(someStructs);
This seems like it would add my vector without having to do any copies, but this seems like something a compiler would already be doing during optimization.
Do you think this is a good strategy?
Edit: Simplified my swap statement due to some suggestions.
The swap trick is as good as it gets with C++03. In C++0x, you'll be able to use the vector's move constructor via std::move to achieve the same thing in a more obvious way.
Another option is to not create a separate vector<MyStruct>, but instead have the code that creates it accept it a a vector<MyStruct>& argument, and operate on it. Then, you add a new empty element to your outer vector<vector<MyStruct>>, and pass a reference to the code that will fill it.
I know this can be accomplished by
using a vector of pointers, but I'd
like to avoid that if possible.
Why?
That would be the most intuitive/readable/maintainable solution and would be much better than any weird hacks anyone comes up with (such as the swap you show).
Tim,
There's a common pattern to solve this. This is called smart pointers, and the best one to use is boost::shared_ptr.
Then, never pass vector by value or store it. Instead, store boost::shared_ptr >. You don't need to care about allocations/deallocations (when the containing vector is destroyed, so will be the others, just as in your code), and you can access the inner members almost the same way. The copy is, however, avoided by means of the smart pointer object's reference counting mechanism.
Let me show you how.
using boost::shared_ptr;
vector<shared_ptr<vector<MyStruct> > vecOfVecs;
shared_ptr<vector<MyStruct> > someStructs(new vector<MyStruct>);
// fill in the vector MyStructs
MyStructs->push_back(some struct.... as you usually do).
//...
vecOfVecs.push_back(someStructs); // Look! No copy!
If you do not already use boost::shared_ptr, I recommend downloading it from boost.org rather than implementing your own. It is really irreplaceable tool, soon to be in the C++ standard library.
You can either do something like vect.push_back(vector<MyStruct>()); and do vect.back().push_back(MyStruct()); or use smart pointers and have a vector of smart pointers to vector<MyStruct>
I think the swap idea is already fine, but can be written much easier:
vecOfVec.push_back(vector<MyStruct>());
vecOfVec.back().swap(someStructs);