C++ - std::list.erase() not removing element - c++

I am having a small issue with a bit of code for a school assignment (I know that's shunned upon here, but I locked myself into using the std::list library and am paying for it). I have a function that has a list of pointers to classes passed into it along with a particular ID belonging to one of those classes that I want to destroy and resize my list. However, with my code, the list is never resized and the values are garbage, that crash my program. So it looks like the actual class is being removed, but the element is never removed from the list...
If I had time to make my own doubly-linked list implementation, I'd iterate over the list looking for the element that I want to delete. If it is found, create a temporary node pointer and point that to the node I am about to delete. Set the previous node's "next" element to the iterator's "next" element, and then delete the iterator node.
But.. using the stl::list implementation, I'm at a loss what to do. Here is what I have so far, where a DOCO is a class, and the elements in the list are pointers to instances of classes. I've looked into remove() vs. erase(), which maybe using both may fix it, but I'm not sure how to implement remove() with an iterator like this.
bool DOCO::kill_doco(std::list < DOCO* > docolist, int docoid)
{
for (std::list<DOCO*>::iterator it = docolist.begin(); it != docolist.end(); )
{
if ((*it)->id == docoid)
{
delete * it;
it = docolist.erase(it);
std::cerr << "item erased\n";
}
else
{
++it;
}
}
std::cerr << "leaving kill\n";
return true;
}

kill_doco(std::list < DOCO* > docolist
this creates a copy of the list. This copy is a list of pointers.
You proceed to modify the copy of the list, and delete an element in it.
The original list (which you copied) still has the original pointer, which is now pointing to a deleted object.
The easy fix is:
kill_doco(std::list < DOCO* >& docolist
C++ is a value-oriented language, unlike languages like Java or C#. The name of something refers to an actual value of that thing, not a reference to it.
Pointers are similarly the value of the address of the object.
Reference like semantics, or pointer-like semantics, can be done in C++. But, unlike Java/C#, by default every object in C++ is an actual value.
People who move from one language to the other (either way) can get confused by this.
The "default" object type in a C++ program is a regular type -- a type that acts like an integer when you copy it around and the like. It is relatively easy to move away from this, but that is the default.
So what you did was akin to:
void clear_bit( int x, int bit ) {
x = x & ~(1 << bit);
}
and being surprised that the value x you passed in wasn't modified by the function. The "dangling" pointer left in the original list is the 2nd thing that bit you.

Related

C++ - Check whether pointer in pointer array is already "filled"

I am working on a project for my University where i have to implement a Hash table. I am quite new to c++, so please forgive me if I am not specific enough or if I have completely wrong assumptions.
Soo..my main problem is that I have a so called "Bucket" which is a struct in my program and which contains a pointer array of N(template parameter) places.
struct Bucket {
T *kptr{ nullptr };
Bucket *bptr{ nullptr }; //For overflow chains (linear Hashing)
Bucket(Bucket *bptr = nullptr) : kptr(new value_type[N]),bptr(bptr) {}
~Bucket() { if(bptr) delete[] bptr; if (kptr) delete[] kptr; }
};
In my main Class named My_Set for example I have an additional Bucket *table of [1<
My first assumption was to initialize the kptr array to nullptr and then in the insert method to make something like
void insert(Bucket &bkt, T &key) {
for (int i=0; i<N, ++i) {
if (bkt.kptr[i]) { //Check on nullptr!
kptr[i] = key;
}
}
}
But that´s not possible because then kptr should be Bucket T **kptr and not Bucket *kptr as far as i understood it.
So, is there any other efficient way to check one single field of an array if it has been assigned to an Object already or not?
IMPORTANT: I am not allowed to use STL Containers, Smart Poitners and similar things which would make the whole thing much easier.
Thanks!
Check whether pointer in pointer array is already “filled”
... So, is there any other efficient way to check one single field of an array if it has been assigned to an Object already or not?
Yes: Initialize the pointer to nullptr. Then, if the pointer has a value other than nullptr, you know that it has been pointed to an object.
However, your professor is correct that your checking is inefficient. On every insert you iterate through all previously inserted objects.
That is unnecessary. You can avoid trying to check whether any of the pointers have been assigned by remembering where the next free pointer is. How can we "remember" things in algorithms? Answer: Using variables. Since you must remember for each instance of your container, you need a member variable.
Since you are using this new variable to remember the next free pointer, how about we name it next_free. Now, considering that the variable must refer to an existing object, what type should it have? A reference would be a good guess, but you must also be able to reassign it once an element is inserted. What can refer to an object like a reference, but can be reassigned? Answer: A pointer. Since this pointer is going to point to a pointer to T, what should be its type? Answer: T**. What should it be initialized to? Answer: The address of the first element of kptr. With such member, insert can be implemented like this:
void insert(T &key) { // why would there be a Bucket argument for insert?
*next_free++ = new T(key); // Note: Do not do this in actual programs. Use
// RAII containers from the standard library instead
}
then kptr should be Bucket T **kptr and not Bucket *kptr as far as i understood it.
Correct. A T* can not point to an array that contains pointers (unless T happens to be a pointer) - it can point to an array of T objects. A T** can point to an array of pointers to T.
Instead of pointers to separately allocated objects, it would be more efficient to use a flat resizable array. But since you are not allowed to use std::vector, you would then have another standard container to re-implement. So consider whether the efficiency is worth the extra work.

Unexpected destructor call when returning object from a pointer

I'm trying to recreate a priority queue implementation I made in C# to C++ as a project to jump into C++ with, but a lot of the nuance is tripping me up. The queue is designed as a template to work on any given class T. The queue will explicitly work with a struct representing objects called Priority Pairs: a pointer to a T object and an associated priority value (int).
The goal of this is to allow the actual objects (the T's) being compared in the queue to be completely separate and only ever be pointed to. I probably don't explicitly need the struct to accomplish this but this is how I'm doing it.
The important bits from the queue implementation:
template <class T>
class PriorityQueue
{
public:
PriorityQueue(const int maxSizeIn)
{
maxSize = maxSizeIn;
queueArray = new PriorityPair<T>*[maxSize];
currentHeapSize = 0;
}
~PriorityQueue()
{
cout << "Destroy Queue with size: " << currentHeapSize << endl;
for (int i = 0; i < currentHeapSize; i++)
{
delete (PriorityPair<T>*)queueArray[i];
}
delete[] queueArray;
}
private:
PriorityPair<T>** queueArray;
The Struct for PriorityPair:
template <class T>
struct PriorityPair
{
PriorityPair(int valueIn, T* objectIn)
{
_PriorityValue = valueIn;
_Object = objectIn;
};
~PriorityPair()
{
cout << "Destroy Pair for object :(" << *_Object << "): << endl;
}
int _PriorityValue;
T* _Object;
};
During the course of my testing, I've found that calling my PeekTop method seems to cause a PriorityPair to have its destructor called. My best guess is that I am accidentally creating a temporary one due to a failure to understand some nuance of the language.
Here's the peek method:
T PeekTop()
{
if (IsEmpty())
return nullptr;
else
return *((PriorityPair<T>)(*queueArray[0]))._Object;
}
Additionally, here is the insert operation (minimally effective insert, does no heap/queue operations):
int InsertElement(PriorityPair<T>* elementIn)
{
//do not insert nulls --
if (elementIn == nullptr)
return -2;
//we could user std::vector or manually expand the array, but a hard max is probably sufficient
if (currentHeapSize == maxSize)
{
return -1;
}
//insert the pointer to the new pair element in at the index corresponding to the current size, then increment the size
queueArray[currentHeapSize++] = elementIn;
return 0;
}
In the main I have the following:
PriorityQueue<string> queue = PriorityQueue<string>(10);
string s1 = "string1";
int code = queue.InsertElement(new PriorityPair<string>(5, &s1));
string i = queue.PeekTop();
cout << "-------\n";
cout << i << endl;
This appears to work, insofar that it does insert the element correctly, but I don't understand if that new pair is behaving as I intend it to. When I run the code the destructor for my Priority Pair is getting called twice. This happens specifically when the function PeekTop is called. Once during the queue's lifetime and once when the queue goes out of scope and is destroyed.
Here is the output from the above code:
Code: 0
Destroy Pair for object :(string1): with priority :(5):
-------
string1
Destroy Queue with size: 1
Destroy Pair for object :(): with priority :(5):
The first destructor call shows the string correctly with its value, but in the second we can see that the string itself has gone out of scope (which is fine and expected).
Aside from the names starting with an underscore, which as people have pointed out in the comments, your problem appears to be in the line return *((PriorityPair<T>)(*queueArray[0]))._Object. Let’s look at this piece by piece, from the inside and working our way out.
queueArray is a PriorityPair<T>**, as declared in PriorityQueue. This could be read as “pointer to pointer to PriorityPair<T>”, but in your case it looks like you mean it to be “raw array of pointer to PriorityPair<T>”, which is also a valid reading. So far so good.
queueArray[0] is a PriorityPair<T>*&, or “reference to pointer to PriorityPair<T>”. References are pretty invisible in C++, and this just means you’re dealing with the actual first element of the array and not a copy. Again, this is a reasonable thing to ask for when trying to peek at the top of the queue.
*queueArray[0] is simply a PriorityPair<T>&, or “reference to PriorityPair<T>”. Again, the reference here just means you’re dealing with the actual thing being pointed to by queueArray[0], and not a copy.
(PriorityPair<T>)(*queueArray[0]) is a PriorityPair<T>, the result of casting the one you already had to a new one. This creates a temporary PriorityPair<T>, which is the one you see destroyed later. There is no programmatic reason to do this cast (your IntelliSense issues are a different question and I don’t know enough about VS to comment about them); it’s already the right type. You can verify that it’s a different one that’s destroyed if you add this to the output, since this is a pointer to the current object and a temporary would need to live somewhere else in memory.
((PriorityPair<T>)(*queueArray[0]))._Object is a T*, or “pointer to T”. In fact, it points to the T that was stored for the top of the priority queue, which is good.
And finally, the full expression *((PriorityPair<T>)(*queueArray[0]))._Object dereferences this to give a T, and the return statement returns a copy of that T. This isn’t affecting the behavior you’re seeing, but if you added destructor calls to the objects you tested with, it would. It would probably be more efficient to return a reference to the T, which would forgo the copying, by changing the return type from T to T& or T const&.
Other issues I noticed, not related to this question, which you might find useful when learning C++ (not a comprehensive list; I mostly wasn’t looking for these):
Both of your constructors should use initializer lists and have empty bodies (yes, new expressions can go in initializer lists, I think literally everybody I’ve spoken to about it either asked this the first time or assumed incorrectly, including me). This will somewhat more efficient and much more idiomatic.
You don’t need to implement a destructor for the PriorityPair (except for learning the nuances of the language); it’s what’s known as a Plain Old Data (POD) type. If you wanted the PriorityPair’s destruction to delete the Ts you would need that, but you want the Ts to be managed completely separately.
As people pointed out in the comments, you aren’t allowed to use those identifier names yourself in case the compiler or standard library want them. This might be fine, it might cause problems for you at compile time, or it might appear to work correctly but send all your users’ browser history and emails to their parents and/or employers. That last is unlikely, but the C++ standard doesn’t forbid it; this is what undefined behavior means. Other allowed behaviors are creating a black hole to destroy the Earth and shooting demons out of your nose, but these are even less likely in practice.
I think like you have the destructor logic for PriorityQueue correct, and it’s easy to mess that sort of thing up. Congratulations!

How do I access pointer to Structure instead of its elements from iterator in STL list

I have a structure of the following form
class THistory
{
/* */
public:
UInt32 userId;
UInt32 trip;
};
List looks like follows
THistory hist2;
std::list<THistory> temp;
std::list<THistory>::iterator it = temp.begin();
hist2.userId=userId;//passed by some function storing in tempory structure
hist2.trip=trip;//passed by some function storing in tempory structure
temp.push_back(hist2);//Pusing into list
My problem is I can access
it->userId and
it->trip
but HOW do I access entire structure. I need to pass entire structure pointer to some other function rather than individual elements. Also, is the above approach correct of using temporary sturcture to populate the elements of structure before pushing into list.
UPDATING based on answers:
I pass the iterator as follows
getLocations(&*it);
definition:
getLocations( THistory *hist){
////
}
My code builds but, it crashes at runtime
"Error: Iterator is deferencable" I steped inside the function, it hits list function call internal to library and crashes here
reference operator*() const
{ // return designated value
return ((reference)**(_Mybase *)this);
}
I am getting confused. Hope it is not silly error
To get the structure, you use the dereference operator * on the iterator. And to get a pointer to the structure you use the address-of operator &.
So e.g. &*it
But (and this is very important) you should first check if the iterator is actually referencing a valid element in the list. The way you show the code in your example, the list is empty and temp.begin() will return the temp.end() iterator, which shouldn't be dereferenced.
However I fail to see why you need a pointer, unless the function you need to call was written by someone else. If you have written, or can rewrite the function, then change it to use a reference (or a reference to a constant) to the structure, and you don't need to use pointers. You really should avoid pointers as much as you can in C++.
As for adding elements to the list, then what you show should work just fine. But if you add a constructor taking the required arguments then you don't need a temporary variable, and could to e.g.
temp.push_back(THistory(userId, trip));

C++ vector implementation - removing elements

I'm implementing a vector type. I'm not troubled by the algorithms or the data structure at all but I am unsure about a remove method. for instance:
bool Remove(Node* node)
{
/* rearrange all the links and extract the node */
delete node;
}
where node is a pointer to the current node that we are at. But if I delete node then how do I prevent this from happening:
Node* currentNode = MoveToRandNode();
Remove(currentNode);
cout << currentNode->value;
If currentNode were a pointer to a pointer it would be easier but...it's not.
You could add another level of abstraction to your iterator (which now is a raw pointer)
If you do not handle raw pointers, but create some sort of iterator class instead of a pointer, it is possible to invalidate the iterator, and thus failing controlled if anyone tries to access the iterator after it has been removed.
class Iterator {
Node operator*() {
if (node) return *node;
else throw Something();}
private:
Node* node;
}
Of course this wrapping of a pointer will come at a cost of some overhead (checking the pointer on each deref). So you will have to decide how safe you want to play. Either document as suggested by others or wrap for safety.
Step back first. You need to define who "owns" the memory pointed to by the vector. Is it the vector itself, or the code that uses the vector? Once you define this, the answer will be easy - either Remove() method should always delete it or never.
Note that you've just scratched the surface of the possible bugs and you answer to "who owns it" will help with other possible issues like:
If you copy a vector, do you need to copy the items within it, or just the pointers (e.g. do a shallow or deep copy
When you destroy a vector, should you destroy the items within it?
When you insert an item, should you make a copy of the item, or does the vector take ownership of it?
well, you cannot do that, but some modifications to your code can improve safety.
Add ref
bool Remove(Node*& node)
{
/* rearrange all the links and extract the node */
delete node;
node = nullptr;
}
check for nullptr
if(currentNode)
cout << currentNode->value;
probably you need to try std::shared_ptr
This is similar to "iterator invalidation". E.g., if you have a std::list l and a std::list::iterator it pointing into that list, and you call l.erase(it), then the iterator it is invalidated -- i.e., if you use it in any way then you get undefined behavior.
So following that example, you should include in your documentation of the Remove method something along the lines: "the pointer node is invalidated, and may not be used or dereferenced after this method returns."
(Of course, you could also just use std::list, and not bother to re-invent the wheel.)
For more info on iterator invalidation, see: http://www.angelikalanger.com/Conferences/Slides/CppInvalidIterators-DevConnections-2002.pdf
In addition what innochenti wrote.
I think you have to decide what is expected/desired behavior of cout << currentNode->value;:
Error - (as innochenti wrote node = nullptr)
Default Value - create node devault_value (which has some default value for its value), and after delete node; do node=default_value

Is returning a std::list costly?

I was wondering if returning a list, instead of returning a pointer to one, was costly in term of performance because if I recall, a list doesn't have a lot of attributes (isn't it something like 3 pointers? One for the current position, one for the beginning and one for the end?).
If you return a std::list by value it won't just copy the list head, it will copy one list node per item in the list. So yes, for a large list it is costly.
If the list is built in the function which is returning it, then you might be able to benefit from the named return value optimisation, to avoid an unnecessary copy. That's specific to your compiler, though. It never applies if for example the list already existed before the function was called (for example if it's a member variable of an object).
A common idiom in C++, to avoid returning containers by value, is to take an output iterator as a parameter. So instead of:
std::list<int> getListOfInts() {
std::list<int> l;
for (int i = 0; i < 10; ++i) {
l.push_back(i);
}
return l;
}
You do:
template<typename OutputIterator>
void getInts(OutputIterator out) {
for (int i = 0; i < 10; ++i) {
*(out++) = i;
}
}
Then the caller does:
std::list<int> l;
getInts(std::back_inserter(l));
Often once the compiler has finished inlining and optimising, the code is more or less identical.
The advantage of this is that the caller isn't tied to a particular collection - for instance he can have the items added to a vector instead of a list if that is more useful for the particular circumstances. If he only needs to see each item once, instead of all of them together, then he can save memory by processing them in streaming mode using an output iterator of his own devising.
The disadvantages are the same as with any template code: the implementation must be available to the caller at compile time, and you can end up with a lot of "duplicate" object code for multiple instantiations of the template. Of course you can use the same pattern without using templates, by taking a function pointer (plus a user data pointer if desired) as a parameter and calling it once with each item, or by defining an IntVisitor abstract class, with a pure virtual member function, and having the caller provide an instance of it.
[Edit: T.E.D points out in a comment that another way to avoid the copy without using templates is for the caller to pass in a list by reference. This certainly works, it just gives the caller less flexibility than the template, and hence is not the idiom used by the STL. It's a good option if you don't want the "advantage of this" that I describe above. One of the original intentions behind the STL, though, is to separate "algorithms" (in this case whatever determines the values) from "containers" (in this case, the fact that the values happen to be stored in a list, as opposed to a vector or an array or a self-sorting set, or just printed out without storing them at all).]
It (as always) depends. The copy constructor may or may not be invoked by return in the following code.
std::list<int> foo() {
std::list<int> bar;
// ...
return bar;
};
It may not be invoked if the compiler applies return value optimization. If the copy-constructor is called, then it is probably more expensive relative to a pointer for larger lists, and if it isn't called, then it is faster to return the straight list (because it avoids a dynamic allocation)
Personally, I don't worry about it and return the straight list. Then, only when my profiler says this a problem do I consider optimizations.
If you return by value the copy constructor will be called and the items will be copied one by one. Sometimes you will be saved by the named value optimization as onebyone pointed out.
Your main options to ensure the copy will not take place are:
Pass in a list by reference to be filled in by the function. This way you tell the function where to put the data and no copy will need to be made because you put it in it's final place.
Allocate a list on the heap and return it. You should return it in a smart pointer like a std::auto_ptr or a boost::shared_ptr to ensure it gets delete and to be exception safe.
I believe, the copy-constructor is called.
It may be costly, in that it will copy every element in the list. More importantly, it has different behaviour: do you want a copy of the list or do you want a pointer to the original list?
You could write your own copy constructor so it does not copy.