I know that push_back() on an std::vector can cause reallocation and therefore invalidate iterators in the pointer. Is there a way of installing a hook on reallocations (which presumably happen very seldom) so that I can adjust iterators appropriately?
Ideally something like this:
class hook; // forward
std::vectorwithhook<T,hook> v;
auto pointer = v.end();
template<> class hook<T> {
void operator()(T *old, T *new) { pointer += new-old; }
}
and then I can push_back() on v and play with pointer with no fear.
IMHO the easiest way to do this would be to have your vectorwithhook::push_back return the new end() and use it like:
pointer = v.push_back(new_item);
NOTE: you would have to do this for all members that change content of the vector (e.g. emplace_back, pop_back, insert etc...)
Alternatively, it should also be possible by creating your own allocator type, which will take a reference to iterator and the container in constructor and update it every time allocator::allocate(...) or allocator::dellocate(...) is called. NOTE that this goes against the principals of STL that was designed to have iterators, containers, allocators separate from one another...
P.S. none of this sounds like a good idea tbh, I would think about reworking the code to avoid keeping the end() iterator instead of doing any of this.
Related
I am using
std::vector<std::vector<int>> S; but the problem can apply to any additional dimension of nesting as well.
To clear content from S, is it sufficient from an efficiency/memory point of view to call S.clear(); or should one first clear the stored container, in this case std::vector<int> and then S.clear(); as:
std::vector<std::vector<int>>::iterator iter;
for (iter = S.begin(); iter != S.end(); iter++) {
iter->clear();
}
S.clear();
Calling clear() on the nested vector(s) is unneeded. When you call clear() on the outermost vector it will destroy each element in the vector. This will in turn destroy any nested vectors.
std::vector is an RAII type, so as long as you are storing an RAII type in it, it will do the right thing, since the types clean up after themselves.
Just call clear on the outermost container. The destructor of the contained containers will clean up their space automatically. The only thing to watch out for is if somewhere down the nesting you have owning raw-pointers. If you have code that does that just change it to use any kind of smart owning pointer, owning the object by value, or another level of container nesting instead of a raw pointer.
To be sure you really release the memory, you may want to do something like:
std::vector<std::vector<int>>().swap(S);
I need to put an std::vector into an std::stack.
Here is my method so far(I am building a card game) :
void CardStack::initializeCardStack(std::vector<Card> & p_cardVector) {
m_cardStack = std::stack<Card>();
//code that should initialize m_cardStack with p_cardVector
}
Note : I cannot change my method signature because it is a imposed by a teacher...
Do I have to iterate over the whole vector ? What is the most efficient way to do this ? The documentation.
I have tried Jens answer but it didn't work.
std::stack doesn't have a constructor which accepts iterators, so you could construct a temporary deque and initialize the stack with this:
void ClassName::initializeStack(std::vector<AnotherClass> const& v) {
m_stackAttribute = std::stack<AnotherClass>( std::stack<AnotherClass>::container_type(v.begin(), v.end()) );
}
However, this copies each element into the container. For maximum efficiency, you should also use move-semantics to eliminate copies
void ClassName::initializeStack(std::vector<AnotherClass>&& v) {
std::stack<AnotherClass>::container_type tmp( std::make_move_iterator(v.begin()), std::make_move_iterator( v.end() ));
m_stackAttribute = std::stack<AnotherClass>( std::move(tmp) );
}
The most efficient way is not using an std::stack at all and just use a std::vector or even better for this use a std::deque.
I've seen and written a lot of C++ code (a lot) but I've yet to find any use for the stack stuff (any meaningful use, that is). It would be different if the underlying container could be changed or having its container type determined at runtime, but this is not the case.
To copy the elements from an std::vector into a std::deque you can just use
std::deque<T> stack(vec.begin(), vec.end());
This will allow the implementation to use the most efficient way to copy the elements.
To explicitly answer your question: yes, the only way to put elements in a stack is to push them in with a loop. This is not efficient but the stack interface doesn't define anything else. However who wrote code accepting an std::stack parameter should be fired (unless s/he promises that it will never happen again) and its code reverted to something more sensible: you would get the same (absence of) "flexibility" but a better interface.
The design problem of stack is that it's parametrized on the underlying container type while instead (to have any meaning) should have been parametrized on the contained element type and receving in the constructor a container for that type (thus hiding the container type). In its present form is basically useless.
I'm trying to do strange things again.
Okay, here's the general idea. I want a std::list (and vector and so on) that actually own the objects they contain. I want to move the values into it, and access them by reference.
Example using a list of unique_ptr:
using namespace std;
list<unique_ptr<T>> items; // T is whatever type
items.push_back(make_unique(...));
items.push_back(make_unique(...));
for ( unique_ptr<T> item : items )
item.dosomething();
With me so far? Good. Now, let's do it with stack semantics and rvalue references. We can't just use a list<T&&> for obvious reasons, so we'd have to make a new class:
using namespace std;
owninglist<T> items;
items.push_back(T());
items.push_back(T());
for ( T& item : items )
item.dosomething();
Of course, I might want an owningstack or owningvector as well, so ideally we want it to be templated:
owning<std::list<T>> items;
The owning<U<T>> class should inherit whatever push_back() and pop_front() etc functions the underlying collection has. Presumably to achieve that, I'd need to code a generic base class, and derive explicit specialisations for the collections that have unusual functions:
template<typename T> owning<std::queue<T>> : owningbase<T> {
void push_front() { ... }
}
I'm getting stuck on the iterators. The begin() and end() functions should return an iterator that works the same as the underlying collection's iterator would, except with an operator*() that returns the item by lvalue reference instead of by value.
We'd need some way to transfer ownership of an item out of the list again. Perhaps the iterator could have an operator~ that returns the item as an rvalue, deletes the item from the list, and invalidates the iterator?
Of course, all this is assuming the underlying std::list (or whatever) can be convinced to take an rvalue. If push_back() copies the value in as an lvalue, then none of this is going to work. Would I be better off coding a container from scratch? If I did, is there some way to put the majority of the code for list, queue, stack and vector into a single base class, to save rewriting pretty much the same class four times over?
Perhaps I could introduce an intermediate class, some kind of wrapper? So owned<list<T>> could inherit from list<refwrapper<T>> or something? I know boost has a reference_wrapper, but I'm not sure it fits this scenario.
If you want to avoid copy elements around you can use std::move.
So if you have a std::list you can populate it with values by moving them in:
SomeBigObject sbo;
std::list<SomeBigObject> list;
list.push_back(SomeBigObject()); // SomeBigObject() is a rvalue and so it is moved
list.push_back(std::move(sbo)); // sbo may not be a rvalue so you have to move it
// For construction you can also use std::list::emplace
list.emplace(list.end()); // construct the value directly at the end of the list
For accessing them you can simply use the ranged based loop:
for(auto& i :list)
...
If you want to move them out of the container you can also use std::move.
The object is moved out of the container but the remains will still be in the container,
so you have to erase them:
for(auto it = list.begin; it != lsit.end();)
{
// the value of *it is moved into obj;
// an empty value of "SomeBigObject" will remain so erase it from the list
SomeBigObject obj = std::move(*it);
it = list.erase(it);
// do something with "obj"
...
}
I'm in need of a container that has the properties of both a vector and a list. I need fast random access to elements within the container, but I also need to be able to remove elements in the middle of the container without moving the other elements. I also need to be able to iterate over all elements in the container, and see at a glance (without iteration) how many elements are in the container.
After some thought, I've figured out how I could create such a container, using a vector as the base container, and wrapping the actual stored data within a struct that also contained fields to record whether the element was valid, and pointers to the next/previous valid element in the vector. Combined with some overloading and such, it sounds like it should be fairly transparent and fulfill my requirements.
But before I actually work on creating yet another container, I'm curious if anyone knows of an existing library that implements this very thing? I'd rather use something that works than spend time debugging a custom implementation. I've looked through the Boost library (which I'm already using), but haven't found this in there.
If the order does not matter, I would just use a hash table mapping integers to pointers. std::tr1::unordered_map<int, T *> (or std::unordered_map<int, unique_ptr<T>> if C++0x is OK).
The hash table's elements can move around which is why you need to use a pointer, but it will support very fast insertion / lookup / deletion. Iteration is fast too, but the elements will come out in an indeterminate order.
Alternatively, I think you can implement your own idea as a very simple combination of a std::vector and a std::list. Just maintain both a list<T> my_list and a vector<list<T>::iterator> my_vector. To add an object, push it onto the back of my_list and then push its iterator onto my_vector. (Set an iterator to my_list.end() and decrement it to get the iterator for the last element.) To lookup, look up in the vector and just dereference the iterator. To delete, remove from the list (which you can do by iterator) and set the location in the vector to my_list.end().
std::list guarantees the elements within will not move when you delete them.
[update]
I am feeling motivated. First pass at an implementation:
#include <vector>
#include <list>
template <typename T>
class NairouList {
public:
typedef std::list<T> list_t;
typedef typename list_t::iterator iterator;
typedef std::vector<iterator> vector_t;
NairouList() : my_size(0)
{ }
void push_back(const T &elt) {
my_list.push_back(elt);
iterator i = my_list.end();
--i;
my_vector.push_back(i);
++my_size;
}
T &operator[](typename vector_t::size_type n) {
if (my_vector[n] == my_list.end())
throw "Dave's not here, man";
return *(my_vector[n]);
}
void remove(typename vector_t::size_type n) {
my_list.erase(my_vector[n]);
my_vector[n] = my_list.end();
--my_size;
}
size_t size() const {
return my_size;
}
iterator begin() {
return my_list.begin();
}
iterator end() {
return my_list.end();
}
private:
list_t my_list;
vector_t my_vector;
size_t my_size;
};
It is missing some Quality of Implementation touches... Like, you probably want more error checking (what if I delete the same element twice?) and maybe some const versions of operator[], begin(), end(). But it's a start.
That said, for "a few thousand" elements a map will likely serve at least as well. A good rule of thumb is "Never optimize anything until your profiler tells you to".
Looks like you might be wanting a std::deque. Removing an element is not as efficient as a std::list, but because deque's are typically created by using non-contiguous memory "blocks" that are managed via an additional pointer array/vector internal to the container (each "block" would be an array of N elements), removal of an element inside of a deque does not cause the same re-shuffling operation that you would see with a vector.
Edit: On second though, and after reviewing some of the comments, while I think a std::deque could work, I think a std::map or std::unordered_map will actually be better for you since it will allow the array-syntax indexing you want, yet give you fast removal of elements as well.
This is a pretty straightforward architectural question, however it's been niggling at me for ages.
The whole point of using a list, for me anyway, is that it's O(1) insert/remove.
The only way to have an O(1) removal is to have an iterator for erase().
The only way to get an iterator is to keep hold of it from the initial insert() or to find it by iteration.
So, what to pass around; an Iterator or a pointer?
It would seem that if it's important to have fast removal, such as some sort of large list which is changing very frequently, you should pass around an iterator, and if you're not worried about the time to find the item in the list, then pass around the pointer.
Here is a typical cut-down example:
In this example we have some type called Foo. Foo is likely to be a base class pointer, but it's not here for simplicity.
Then we have FooManger, which holds a list of shared_ptr, FooPtr . The manager is responsible for the lifetime of the object once it's been passed to it.
Now, what to return from addFoo()?
If I return a FooPtr then I can never remove it from the list in O(1), because I will have to find it in the list.
If I return a std::list::iterator, FooPtrListIterator, then anywhere I need to remove the FooPtr I can, just by dereferencing the iterator.
In this example I have a contrived example of a Foo which can kill itself under some circumstance, Foo::killWhenConditionMet().
Imagine some Foo that has a timer which is ticking down to 0, at which point it needs to ask the manager to delete itself. The trouble is that 'this' is a naked Foo*, so the only way to delete itself, is to call FooManager::eraseFoo() with a raw pointer. Now the manager has to search for the object pointer to get an iterator so it can be erased from the list, and destroyed.
The only way around that is to store the iterator in the object. i.e Foo has a FooPtrListIterator as a member variable.
struct Foo;
typedef boost::shared_ptr<Foo> FooPtr;
typedef std::list<FooPtr> FooPtrList;
typedef FooPtrList::iterator FooPtrListIterator;
struct FooManager
{
FooPtrList l;
FooPtrListIterator addFoo(Foo *foo) {
return l.insert(l.begin(), FooPtr(foo));
}
void eraseFoo(FooPtrListIterator foo) {
l.erase(foo);
}
void eraseFoo(Foo *foo) {
for (FooPtrListIterator it=l.begin(), ite=l.end(); it!=ite; ++it) {
if ((*it).get()==foo){
eraseFoo(it);
return;
}
}
assert("foo not found!");
}
};
FooManager g_fm;
struct Foo
{
int _v;
Foo(int v):_v(v) {
}
~Foo() {
printf("~Foo %d\n", _v);
}
void print() {
printf("%d\n", _v);
}
void killWhenConditionMet() {
// Do something that will eventually kill this object, like a timer
g_fm.eraseFoo(this);
}
};
void printList(FooPtrList &l)
{
printf("-\n");
for (FooPtrListIterator it=l.begin(), ite=l.end(); it!=ite; ++it) {
(*it)->print();
}
}
void test2()
{
FooPtrListIterator it1=g_fm.addFoo(new Foo(1));
printList(g_fm.l);
FooPtrListIterator it2=g_fm.addFoo(new Foo(2));
printList(g_fm.l);
FooPtrListIterator it3=g_fm.addFoo(new Foo(3));
printList(g_fm.l);
(*it2)->killWhenConditionMet();
printList(g_fm.l);
}
So, the questions I have are:
1. If an object needs to delete itself, or have some other system delete it, in O(1), do I have to store an iterator to object, inside the object? If so, are there any gotchas to do with iterators becoming invalid due other container iterations?
Is there simply another way to do this?
As a side question, does anyone know why and of the 'push*' stl container operations don't return the resultant iterator, meaning one has to resort to 'insert*'.
Please, no answers that say "don't pre-optimise", it drives me nuts. ;) This is an architectural question.
C++ standard in its [list.modifiers] section says that any list insertion operation "does not affect the validity of iterators and references", and any removal operation "invalidates only the iterators and references to the erased elements". So keeping iterators around would be safe.
Keeping iterators inside the objects also seems sane. Especially if you don't call them iterators, but rather name like FooManagerHandlers, which are processed by removal function in an opaque way. Indeed, you do not store "iterators", you store "representatives" of objects in an organized structure. These representatives are used to define a position of an object inside that structure. This is a separate, quite a high-level concept, and there's nothing illogical in implementing it.
However, the point of using lists is not just O(1) insert/remove, but also keeping elements in an order. If you don't need any order, then you would probably find hash tables more useful.
The one problem I see with storing the iterator in the object is that you must be careful of deleting the object from some other iterator, as your objects destructor does not know where it was destroyed from, so you can end up with an invalid iterator in the destructor.
The reason that push* does not return an iterator is that it is the inverse of pop*, allowing you to treat your container as a stack, queue, or deque.