Popping the second last - c++

I'm a C# programmer having problems with messy pointers and I just can't find out what the mistake is.. I could use some help with the list
So basically I have something like a stack of cards and these cards are saved in a list. I just want to take the upper most and return it to the function. I could use pop_back() but the last card has to stay as it is because it is the cardback (I'm making it later with textures and stuff)
Card * CardStack::HandOut()
{
if (m_Stack.size() > 1)
{
list<Card *>::iterator it = m_Stack.end();
advance(it, -2);
Card *ret = *it;
Card tmp = *ret;
Card *tmpp = &tmp;
m_Stack.remove(ret);
return tmpp;
}
return NULL;
}
So I want to always pop the second last Card back.
I'm sure its a total beginner mistake :(

You are returning a pointer to a local variable,
Card tmp = *ret;
Card *tmpp = &tmp;
m_Stack.remove(ret);
return tmpp;
that doesn't exist anymore after the function exited. So when you use the pointer later, you invoke undefined behaviour.
You should not bother with tmp and tmpp, returning ret ought to do it, the remove doesn't destroy the card, it just removes (the pointer to) it from the stack.

You could just erase the item pointer by the iterator directly. This also ensures the removal is O(1) instead of O(n) using .remove(), and avoids removing extra items if the contents are not unique.
std::list<Card*>::iterator it = m_Stack.end();
std::advance(it, -2);
Card* res = *it;
m_Stack.erase(it);
return res;
Note that it is not idiomatic in C++ to store raw pointers. It is better to store the object by value (i.e. use list<Card>) if copying is cheap, or use a smart-pointer (e.g. list<shared_ptr<Card> >) so the memory can be collected automatically when it is no longer used.

Related

C++: struct pointer in map structure

I declared a struct like this, and the following data structures
struct piece{
int start, height, end;
piece(int a, int b, int c){
start = a; height = b; end = c;
}
};
vector<piece> piecesTog;
map <int,piece*> data;
Then, when I read the elements I do this:
while(scanf("%d %d %d", &aux1, &aux2, &aux3) != EOF){
piecesTog.push_back( piece(aux1, aux2, aux3) );
data[a] = data[c] = &piecesTog[tam];
}
Well, until now, I have had no problem.
However, later in the program, I have to use the piece* part, to do so, I use an iterator like this
for(map< int, piecesTog* >::iterator it = data.begin(); it != data.end(); it++){
piece* aux = it->second;
...
}
I want to have access to the structure that the it->second points, but I tried everything and nothing worked.
I printed the memory adress of it->second and &piecesTog[tam] and they are the same, but when I do (*aux).height or it->second->height they give number completely crazy, probably some trash.
I have no clue why that is happening.
If anyone has any idea how to fix it, I would appreciate it.
while(scanf("%d %d %d", &aux1, &aux2, &aux3) != EOF){
piecesTog.push_back( piece(aux1, aux2, aux3) );
data[a] = data[c] = &piecesTog[tam];
}
is almost certainly not following the Iterator invalidation rules.
piecesTog.push_back( piece(aux1, aux2, aux3) );
can trigger a resize which typically creates a new datastore, copies the elements from the old data store to the new one and then deletes the old datastore, leaving the pointers cached by
data[a] = data[c] = &piecesTog[tam];
dangling. When you use those pointers some time in the future, Ka-Blammo! Undefined Behaviour and an easily identified crash if you're lucky.
Insufficient information has been provided to supply a definitive solution, but here are a few general alternatives (in order of attractiveness):
If you know ahead of time the number of pieces that will go into piecesTog, you can reserve storage to eliminate the need to resize the vector.
If elements are only added to the end of the vector and no elements are ever removed, you can store the indexes of the elements rather than pointers to them. If the ordering never changes, the indexes will always refer to the correct elements no matter how many more items are added.
If it is possible to do so, rewrite the reader to load all of the pieces into piecesTog and then build the maps.
The above options all assume that piecesTog is assembled all at once and then left alone. If your insertion is more free-form, you sort the structure or you remove elements, you'll need to use a data structure with more favourable invalidation rules such as std::list.

Prevent construction/initialization of array elements in C++

I have the following declaration (yes, its using the runtime array length extension)
Iterator traversal_stack[depth];
My problem is that the compiler attempts to initialise array members. In fact, this code does not compile, because Iterator has no public default constructor. While I understand where this behaviour comes from, in my case it is really unwanted, because the access pattern to the array
guarantees that:
an array element will be written to at most once and
no element will be ever read without being written.
Any violation from this pattern means that the algorithm is messed up. Below is a pseudocode that illustrates how the array is used (it's essentially a heavily optimised stack for traversing a balanced tree)
Iterator traversal_stack[depth];
auto current_node = root;
auto current_level = 0;
// traverse the tree, looking for a suitable insertion point
// within every node, record visited nodes (vie the iterator struct)
while(current_level < depth) {
// find the optimal insertion entry (pointed to by the iterator)
auto iter = as_branch(current_node).iterate();
iter = find_best_insertion_point(iter, to_inserted_object);
// record the visited node in the stack
// a value is pushed onto the stack exactly once!
traversal_stack[current_level] = iter;
// get to the next level of the tree
current_node = iter.node_for_entry();
current_level += 1;
}
// ... insert the data into the found terminal node
// now unroll the stack, adjusting the node metadata
current_level -= 1;
while(current_level >= 0) {
// the element of the array is necessarily initialized
// by assignment in the previous loop
auto iter = traversal_stack[current_level];
insertion_state = adjust_node_metadata_for(iter);
current_level -= 1;
}
I know that I could just provide the default constructor and be done with it, but I would really like to avoid it. Besides possible (but probably less important) performance considerations, the biggest issue with a default constructor is that it would have to introduce some sort of default invalid state, messing up the iterator semantics big time.
So, my question: can I declare the array like that leave the values completely undefined? I am ok if the solution is specific to Clang using the latest C++1z draft + custom extensions.
If you really want to use VLA and uninitialized object.
A way is to use std::aligned_storage for creating uninitialized memory blocks, and then cast it to a reference to array.
#include <type_traits>
struct Iterator {
Iterator() = delete;
};
int main() {
int length = 10;
std::aligned_storage_t<sizeof(Iterator), alignof(Iterator)> memory_blocks[length];
auto &array = reinterpret_cast<Iterator (&)[length]>(memory_blocks);
return 0;
}

Create pointer to pointer in while statement issue

in Visual Studio 2010 i create a while statement in which i assign a pointer to pointer to a map.
Example:
std::map<int,std::tuple<int,std::string>** > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = &t;
dmap[i + 1 ] = &t;
i++;
}
.
.
.
for (auto it = d.begin();it!=d.end();++it)
{
if(*(it->second) != nullptr){
delete *(it->second);
*(it->second) = nullptr;
}
}
The problem is that the address of &t is always the same and so at the end the map always contains , for all keys that i entered, the last *t value.
What's the problem? (Resolved)
[Edit]
Now i modify the code beacause before it was incomplete, if i want to avoid to delete nullptr i need to have a pointer to pointer. Or not?
The problem is that you're putting a pointer to a local variable t into the map. After each loop, t is destroyed and the pointer is no longer valid.
I've no idea why you're using pointers at all, let alone pointers to pointers. You probably want to put the tuples themselves in the map:
std::map<int,std::tuple<int,std::string>> dmap;
for (int i = 0; i<3; ++i){
dmap[i] = {10+i, "test"};
}
i create a while statement in which i assign a pointer to pointer to a map
Sorry for saying this, but it sounds to me like you have bigger problems than the fact that t is the same (this looks like the xy problem).
Consider (in order) one of these alternatives:
store your tuples by value
store your tuples by single pointer (worse than "by value", better than "by pointer to pointer"). If you can do this, consider declaring your map over std::shared_ptr<std::tuple<...>>)
if you really need a map of pointers to pointers to tuples, consider creating a minimal proxy object that acts like a smart pointer to pointer internally (and manages the allocations for you in a safe manner) and like a regular type from the outside (and redeclare your map accordingly).
Either way, if you really need a map of pointers to pointers to tuples (for some reason), the allocation should be done like this:
std::map<int,std::tuple<int,std::string>**> dmap;
int i=0;
while (i<3) {
*dmap[ i ] = new std::tuple<int,std::string>{10 + i, "test"};
++i;
}
(The way you did it added the address of the same local (stack) variable to the map, which would lead to undefined behavior after you exit the local function).
Why are you interested in std::tuple<int,std::string>** ?
Wouldn't a std::tuple<int,std::string>* be sufficient ?
std::map<int,std::tuple<int,std::string>* > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
i++;
}
Well, the address of t is always the same, because it is local variable that is stored on your stack. Each time you enter the block, t will be allocated on the same spot (as you're destroying t after you get out of your while body).
Instead, you need to allocate it on the heap (if this is really what you want to do).
std::tuple<int,std::string>** t = new std::tuple<int,std::string>*();
*t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
I can't see what you're trying to accomplish, but this would be a better solution:
std::map<int,std::tuple<int,std::string>* > dmap;
int i=0;
while (i<3){
std::tuple<int,std::string>* t = new std::tuple<int,std::string>(10+i,std::string("test"));
dmap[i] = t;
i++;
}
Even better would be to use smart pointer instead raw one.
Even better would be to store objects by value (no pointers at all).

Sorting an array of valid and invalid numbers in c++ for an embedded system

I am writing a program in C++ that will be used with Windows Embedded Compact 7. I have heard that it is best not to dynamically allocate arrays when writing embedded code. I will be keeping track of between 0 and 50 objects, so I am initially allocating 50 objects.
Object objectList[50];
int activeObjectIndex[50];
static const int INVALID_INDEX = -1;
int activeObjectCount=0;
activeObjectCount tells me how many objects I am actually using, and activeObjectIndex tells me which objects I am using. If the 0th, 7th, and 10th objects were being used I would want activeObjectIndex = [0,7,10,-1,-1,-1,...,-1]; and activeObjectCount=3;
As different objects become active or inactive I would like activeObjectIndex list to remain ordered.
Currently I am just sorting the activeObjectIndex at the end of each loop that the values might change in.
First, is there a better way to keep track of objects (that may or may not be active) in an embedded system than what I am doing? If not, is there an algorithm I can use to keep the objects sorted each time I add or remove and active object? Or should I just periodically do a bubble sort or something to keep them in order?
You have a hard question, where the answer requires quite a bit of knowledge about your system. Without that knowledge, no answer I can give would be complete. However, 15 years of embedded design has taught me the following:
You are correct, you generally don't want to allocate objects during runtime. Preallocate all the objects, and move them to active/inactive queues.
Keeping things sorted is generally hard. Perhaps you don't need to. You don't mention it, but I'll bet you really just need to keep your Objects in "used" and "free" pools, and you're using the index to quickly find/delete Objects.
I propose the following solution. Change your object to the following:
class Object {
Object *mNext, *mPrevious;
public:
Object() : mNext(this), mPrevious(this) { /* etc. */ }
void insertAfterInList(Object *p2) {
mNext->mPrev = p2;
p2->mNext = mNext;
mNext = p2;
p2->mPrev = this;
}
void removeFromList() {
mPrev->mNext = mNext;
mNext->mPrev = mPrev;
mNext = mPrev = this;
}
Object* getNext() {
return mNext;
}
bool hasObjects() {
return mNext != this;
}
};
And use your Objects:
#define NUM_OBJECTS (50)
Object gObjects[NUM_OBJECTS], gFree, gUsed;
void InitObjects() {
for(int i = 0; i < NUM_OBJECTS; ++i) {
gFree.insertAfter(&mObjects[i]);
}
}
Object* GetNewObject() {
assert(mFree.hasObjects());
Object obj = mFree->getNext();
obj->removeFromList();
gUsed.insertAfter(obj);
return obj;
}
void ReleaseObject(Object *obj) {
obj->removeFromList();
mFree.insertAfter(obj);
}
Edited to fix a small glitch. Should work now, although not tested. :)
The overhead of a std::vector is very small. The problem you can have is that dynamic resizing will allocate more memory than needed. However, as you have 50 elements, this shouldn't be a problem at all. Give it a try, and change it only if you see a strong impact.
If you cannot/do not want to remove unused objects from a std::vector, you can maybe add a boolean to your Object that indicates if it is active? This won't require more memory than using activeObjectIndex (maybe even less depending on alignment issues).
To sort the data with a boolean (not active at the end), write a function :
bool compare(const Object & a, const Object & b) {
if(a.active && !b.active) return true;
else return false;
}
std::sort(objectList,objectList + 50, &compare); // if you use an array
std::sort(objectList.begin(),objectList.end(), &compare); // if you use std::vector
If you want to sort using activeObjectIndex it will be more complicated.
If you want to use a structure that is always ordered, use std::set. However it will require more memory (but for 50 elements, it won't be an issue).
Ideally, implement the following function :
bool operator<(const Object & a, const Object & b) {
if(a.active && !b.active) return true;
else return false;
}
This will allow to use directly std::sort(objectList.begin(), objectList.end()) or declare an std::set that will stay sorted.
One way to keep track of active / inactive is to have the active Objects be on a doubly linked list. When an object goes from inactive to active then add to the list, and active to inactive remove from the list. You can add these to Object
Object * next, * prev;
so this does not require memory allocation.
If no dynamic memory allocation is allowed, I would use simple c-array or std::array and an index, which points into last+1 object. Objects are always kept in sorted order.
Addition is done by inserting new object into correct position of sorted list. To find insert position lower_bound or find_if can be used. For 50 element, second probably will be faster. Removal is similar.
You should not worry about having the list sorted, as writing a method to search in a list of indices what are the ones active would be O(N), and, in your particular case, amortized to O(1), as your array seems to be small enough for this little extra verification.
You could maintain the index of the last element checked, until it reaches the limit:
unsigned int next(const unsigned int& last) {
for (unsigned int i = last + 1; i < MAX_ARRAY_SIZE; i++) {
if (activeObjectIndex[i] != -1) {
return i;
}
}
return -1;
}
However, if you really want to have a side index, you can simply double the size of the array, creating a double linked list to the elements:
activeObjectIndex[MAX_ARRAY_SIZE * 3] = {-1};
activeObjectIndex[i] = "element id";
activeObjectIndex[i + 1] = "position of the previous element";
activeObjectIndex[i + 2] = "position of the next element";

advice on memory management when using STL priority_queue

I'm trying to adapt from Java to C++ and am unsure about the correct way to manage memory when I pop() an item from an STL priority_queue.
Am I supposed to use delete to clean up items removed from the queue that I no longer need? If so, how? If not, why not?
I have written myself a small program to learn how to use a priority_queue (code below). In this program it's no big deal if there is a memory leak, because it's so small-scale and ends so quickly. But I want to learn the correct way of doing things so I can write a program that correctly handles a much larger queue without memory leaks.
The thing I do not understand is this: top() returns a reference rather than a pointer. But I can't use delete on a reference, can I?
Can someone point me in the right direction here?
--------------------
struct PathCost{
int dest;
int cost;
PathCost(int _dest, int _cost){
dest = _dest;
cost = _cost;
}
bool operator<(PathCost other) const;
bool operator>(PathCost other) const;
};
bool PathCost::operator<(PathCost other) const{
return cost < other.cost;
}
bool PathCost::operator>(PathCost other) const{
return cost > other.cost;
}
int main(){
PathCost pc = PathCost(1, 2);
pc = PathCost(3, 4);
PathCost* pcp = new PathCost(5, 6);
delete pcp;
priority_queue<PathCost,
vector<PathCost>,
greater<vector<PathCost>::value_type> > tentativeQ;
cout << "loading priority queue ...\n";
tentativeQ.push(PathCost(8, 88));
tentativeQ.push(PathCost(5, 55));
tentativeQ.push(PathCost(7, 77));
tentativeQ.push(PathCost(4, 44));
cout << "\nlist items on queue in priority order ...\n";
while (!tentativeQ.empty()){
pc = tentativeQ.top();
cout << "dest:" << pc.dest << " cost:" << pc.cost << endl;
tentativeQ.pop();
/* DO I NEED TO DO MEMORY CLEANUP AT THIS POINT? */
}
}
Am I supposed to use delete to clean up items removed from the queue that I no longer need? If so, how? If not, why not?
You do not need to perform any cleanup, because the priority_queue is holding PathCost objects. When they get removed from the queue, their destructor is called automatically, as per the rules of the language.
Behind the scenes, the story can be somewhat more complicated. The inserting an item into the priority_queue data structure will, in general, result in the dynamic allocation of a copy of that object. But resource allocation and de-allocation is taken care of by the underlying data structure (by default std::vector) so you do not have to worry about memory management. Standard library containers and container adapters are said to have value semantics.
The thing I do not understand is this: top() returns a reference rather than a pointer. But I can't use delete on a reference, can I?
The priority_queue is said to own the elements it holds, so if you take a reference to one of its elements, you cannot delete it. In fact, you cannot know if it needs to be deleted at all or not. Furthermore, although you have access to references of elements in the queue, you are not forced to keep references to these elements. You can also make your own copy:
const PathCost& pRef = tentativeQ.top(); // take constant reference to top element
PathCost p = tentativeQ.top(); // make copy of last element
In the first case, you have to be careful that you do not use that reference after the top element has been removed via a call to pop().