I have a c++ stack named pages.
As I have no clear() function to clear a stack, I wrote the following code:
stack<string> pages;
//here is some operation
//now clearing the stack
while(!pages.empty())
pages.pop();
Now my question: is there a better efficient way to clear the stack?
In general you can't clear copying containers in O(1) because you need to destroy the copies. It's conceivable that a templated copying container could have a partial specialization that cleared in O(1) time that was triggered by a trait indicating the type of contained objects had a trivial destructor.
If you want to avoid loop.
pages=stack<std::string>();
or
stack<std::string>().swap(pages);
I don't think there is a more efficient way. A stack is a well defined data type, specifically designed to operate in a LIFO context, and not meant to be emptied at once.
For this you could use vector or deque (or list), which are basically the underlying containers; a stack is in fact a container adaptor. Please see this C++ Reference for more information.
If you don't have a choice, and you have to use stack, then there is nothing wrong with the way you do it. Either way, the elements have to be destroyed if they were constructed, whether you assign a new empty stack or pop all elements out or whatever.
I suggest to use a vector instead; it has the operations you need indeed:
size (or resize)
empty
push_back
pop_back
back
clear
It is just more convenient, so you can use the clear method. Not sure if using vector is really more performant; the stack operations are basically the same.
What about assigning a new empty stack to it?
pages = stack<string>();
It won't remove elements one by one and it uses move assignment so it has the potential to be quite fast.
make it into a smart pointer:
stack.reset();
stack = make_shared<stack<string>>();
What about subclassing std::stack and implementing a simple clear() method like this, accessing underlying container c ?
public:
void clear() { c.clear(); }
Related
In my application there's a part that requires me to make a copy of a container. At the moment I use std::vector (but might consider using something else). The application is very sensitive with regard to the latency. So, I was looking for a way to make a copy of a vector as fast as possible. I found that memcpy does it better than anything else. However, it does not change the internal size of the vector. I.e. vector.size() would still give me 0.
I know what slippery path I am on. I do not mind throwing away safety checks. I do know how many elements are being copied. I do not want to use vector.resize() to change the size of the destination vector (it is a slow operation).
Question:
std::vector<my_struct> destination_vector;
destination_vector.reserve(container_length);
std::memcpy(destination_vector.data(), original_vector.data(), sizeof(my_struct)*container_length);
After the code above I need to tell my destination_vector what size it is. How do I do this?
Thank you.
You must to actually resize() the vector before you copy stuff to it using memcpy():
destination_vector.resize(container_length);
But it would be better to avoid the use of memcpy() in the first place and use the mechanisms to copy vector content which is offered by vector, as suggested in the other answers:
std::vector<my_struct> destination_vector(original_vector);
or if the destination_vector instance already exists:
destination_vector.insert(destination_vector.begin(), original_vector.begin(), original_vector.end);
or, the fastest if you do not need the original content any more:
destination_vector.swap(original_vector);
All of these variants will be as fast or even faster than your memcpy()variant. If you experience slowness then see 2.:
You probably have a non-trivial default constructor in my_struct. Remove it, or insert a trivial (empty) default constructor to speed things up (to avoid construction of many elements which you never use).
If my_structcontains non-POD data members (like std::string) you cannot use memcpy() at all.
(Side note: You rarely want to call reserve(). The vector maintains its own internal storage in such a way that is always allocates more than is actually needed, exponentially, to avoid frequent resizes/copying when frequently appending elements.)
resize() is not a slow operation. It is as fast as any memory allocation.
Does my_struct have a non-trivial default constructor? Remove it and take care of initialization manually. This might be the reason why you say resize() is slow. It will actually construct your objects. But since you can apparently memcpy() your objects you can probably get away with a trivial (empty) default constructor.
How to manually assign vector's size?
You can't. You can only modify vector's size through the modification functions that add or remove elements such as insert, clear, resize etc.
After the code above I need to tell my destination_vector what size it is. How do I do this?
The mentioned code above has undefined behaviour, so it doesn't matter what you do after it.
A simple and efficient way to copy a vector is:
std::vector<my_struct> destination_vector(original_vector);
Your snippet has undefined behaviour, you can't memcpy into an empty vector, even if you have reserved space. It may also be undefined behaviour to memcpy any my_struct objects, if it isn't a TriviallyCopyable type.
You can construct the vector as a copy of the source directly. Most likely your compiler will emit code identical (or faster) than your original snippet, if my_struct is TriviallyCopyable.
std::vector<my_struct> destination_vector(original_vector.begin(), original_vector.begin() + container_length);
The following code inherits std::priority_queue and provides clear() which calls the internal std::vector's clear()
#include<iostream>
#include<queue>
using namespace std;
template<class type>
struct mypq :public priority_queue<type> {
void clear(){
this->c.clear();
}
};
mypq<int>pq;
int main() {
for(int i=0;i<10;++i)
pq.push(i);
pq.clear();
for(int j=-5;j<0;++j)
pq.push(j);
while (!pq.empty()){
cerr<<pq.top()<<endl;
pq.pop();
}
}
When I tested it with g++, MSVC++ and clang, it produces the expected output:
-1
-2
-3
-4
-5
But I haven't seen any guarantee for this, i.e. clearing the internal vector will be the same as calling pop() when the priority_queue isn't empty. Although I know other ways to clear it such as swap or assign it using an empty priority_queue, I think if this code can work well, it would be more efficient since the allocated memory in the vector is reusable. So I wonder if this code is portable or won't always work?
But I haven't seen any guarantee for this, i.e. clearing the internal vector will be the same as calling pop() when the priority_queue isn't empty.
Because that's not the same thing. A std::priority_queue is a specifically designed container adaptor that keeps things ordered via strict weak ordering. If you don't specify the type of container the queue will have (which you don't in the example), then the default type is a std::vector.
So calling pop() on a non-empty priority queue will have the effect of removing the top element from the queue while calling clear() on the underlying container will remove all elements from the queue, not just the top most.
Although I know other ways to clear it such as swap or assign it using an empty priority_queue, I think if this code can work well, it would be more efficient since the allocated memory in the vector is reusable. So I wonder if this code is portable or won't always work?
According to the reference, the underlying c member object is protected, so accessing the way you are should be guaranteed across compilers, that is, calling this->c.clear(); should be portable (anecdotally, it works on g++ 4.2.1 on an older version of OpenBSD).
As far as efficiency is concerned, it would somewhat depend. Doing something like this->c.clear(); vs. q = priority_queue <int>(); might not be that different in terms of memory usage or complexity, though you would have to test it on the different platforms to verify. However, doing something like this->c.clear(); vs. while(!q.empty()) { q.pop(); }, would be more efficient.
In terms of memory efficiency, the pop function of the priority queue calls the underlying containers pop_back function, and neither the pop_back nor the clear affect the underlying vector's capacity, so there's not really any "savings" to be had in that way; though with this, you could resize the vector to increase/decrease capacity if you had a specific need to.
Just remember that the priority queue pop function calls the underlying containers pop_back function, and calling pop_back on an empty container is undefined behavior.
Hope that can help.
A very good question. While I can't seem to find any strict guarantee that it is a correct method, there are some reasons to think that it is.
For example, consider the docs for operator=:
Copy assignment operator. Replaces the contents with a copy of the
contents of other. Effectively calls c = other.c;. (implicitly
declared)
Since the other queue may be of a different size, this essentially means that there is no internal state that is dependent on size. Moreover, it also implies that assigning an empty queue essentially replaces the container with an empty one and does nothing else.
With that in mind, and the fact that a reasonable implementation of a priority queue would hardly need to maintain any state except for the size of the queue, I believe it can be safely assumed that clearing the underlying container is a valid way to empty the queue.
I have a vector containing objects of type STL map, and I do vector.push_back(some map).
This unfortunately calls the map copy constructor, and wastes a lot of time. I understand that i can get around this by keeping a vector of (smart) pointers to maps - but this got me wondering - I read that STL anyway keeps its data on the heap and not on the stack - so why is the copy ctor not O(1) time, by simply copying pointers?
If you don't need the original map anymore after pushing back a copy back into the vector, write:
some_vector.push_back(std::move(some_map));
If you don't have a C++11 compiler yet, add an empty map and then swap that with the original:
some_vector.resize(some_vector.size() + 1);
some_vector.back().swap(some_map);
To answer your question directly: to do that, it would have to start with some sort of copy on write mechanism -- when you put something into a vector, it's required to be a copy of the original (or at least act like one). For example, if I push a map onto my vector, and then remove an item from the original map, that item should still be there in the copy of the map that was pushed onto the vector.
Then it would have to keep track of all the pointers, and ensure that the pointee (the map in this case) remained valid until all those pointers were themselves destroyed. It's certainly possible to do that. Quite a few languages, for example, provide garbage collection largely for this reason. Most of those change the semantics of things, so when/if you (for example) create a vector of maps, putting a map into the vector has reference semantics -- i.e., when you modify the original map, that's supposed to change any "copies" of it that you put into other collections.
As you've observed, you can do any/all of the above in C++ if you really want. The reason it doesn't right now is that most of the C++ standard library is built around value semantics instead of reference semantics. Either is (IMO, anyway) a perfectly valid and reasonable approach -- some languages take one, others take the other. Either/both can work just fine, but value semantics happens to be the choice that was made in C++.
If you want to copy pointers, create a vector of pointers to map. You can do that.
std::vector<std::map<A,B>* > x;
It doesn't do this automatically because it can't know who you want to manage the memory. Should the objects of the map be destroyed when the vector goes out of scope. What if the original map is still in scope?
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.
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);