Removing a single pointer from a boost::ptr_list list? - boost

If I create a bunch of elements in a boost::ptr_list container how can I remove individual pointers from it? Say I do this:
boost::ptr_list intlist;
int *i = new int(3);
intlist.Add(i);
int *i2 = new int(1);
intlist.Add(i2);
int *i3 = new int(6);
intlist.Add(i3);
How can I remove say i3 and not i or i2 from the list?

The pop_back() command deletes the last element of a list. Boost's implementation of ptr_list encapsulates a std::list, so all of the commands on this page are equally valid with Boost's pointer wrappers.
Since you changed your question, see the erase command. You won't find an answer except by using the std::list interface.

Related

memory leak delete linked list node

Newbie question. Suppose I have a C++11 linked list implementation with
template <typename X> struct Node {
X value;
Node* next;
Node(X x) {
this->value = x;
this->next = nullptr;
}
};
and later in the code I create a pointer variable
X x = something;
Node<X>* node = new Node(x);
and still later I do
delete node;
Is the x stored within node destructed when this statement is executed?
You may tell me I should use std::list instead of writing my own, but right
now I'm just trying to educate myself on pointers.
Since you did not provide a custom desctructor the compiler will generate the default one for you, which (by default) call destructors on its elements.
Now, the answer to your question really depends on what your x is :) If it is an object that has a destructor (like std::string) - it will be properly destroyed. But if it is a "naked pointer" (like int *) - it will not get destroyed and will cause a memory leak.
N.B. You create your x on a stack so I really-really-really hope that X provides proper copy semantics, otherwise you may end up with an invalid object stored in your node!

C++ std::sort of const struct

I have the following struct in a vector
struct ub_node {
const size_t index;
const double ub_dist;
bool operator<(const ub_node &rhs) const { return ub_dist< rhs.ub_dist; }
};
I would like to sort that vector. I have tried using std::sort but I get a compile error:
error: use of deleted function ‘ub_node& ub_node::operator=(ub_node&&)’ with a reference to the line where I do std::sort(result.begin(), result.end());, where result is of type vector<ub_node>.
As far as I understand, the const does NOT affect the execution time, but merely ensures that the programmer (me) does not do anything stupid. If this is the case, I might remove the const and try to ensure that I do not change the node afterwards. Can someone confirm this? Or help me to sort it?
As far as I understand, the const does NOT affect the execution time, but merely ensures that the programmer (me) does not do anything stupid.
Correct.
Sorting a vector swaps the elements around, which is not possible if the elements have immutable data (with your ub_node type you can't even remove or insert an element anywhere except the end of the vector, because that also needs to modify existing elements).
I suggest you remove the const from your members, so the type is possible to modify, and then structure your code so that parts of the program which shouldn't modify it only interacts with the class through const ub_node& or const ub_node*.
That means that the class is modifiable when necessary, but won't be modified by parts of the program that aren't supposed to modify it.

C++11 lock free stack

I'm reading C++ Concurrency in Action by Anthony Williams, and don't understand its push implementation of the lock_free_stack class.
Why on earth the atomic load is not in the while loop ? The reason he gave is:
You therefore don’t have to reload head each time through the loop,
because the compiler does that for you.
But I don't get the picture. Can someone shed some light on this?
template<typename T>
class lock_free_stack
{
private:
struct node
{
T data;
node* next;
node(T const& data_) :
data(data_)
{}
};
std::atomic<node*> head;
public:
void push(T const& data)
{
node* const new_node=new node(data);
new_node->next=head.load();
while(!head.compare_exchange_weak(new_node->next,new_node));
}
};
The key is in the interface to compare_exchange_weak, which in this case takes 2 arguments. The first is a reference to the expected value, and the second is the desired. If the current value of the atomic is not equal to the expected input, it will return false and the expected input is set to the current value.
So in this case, what it's doing is setting new_node->next = head. Then, it's saying if head is still equal to new_node->next, swap it into head. If it's no longer that value, it uses the reference to new_node->next to assign it the current value of head. Since every iteration of the loop that fails also replaces new_node->next with the current value of head, there is no read to duplicate that in the body of the loop.
From the documentation of compare_exchange_weak:
Atomically compares the value stored in *this with the value of
expected, and if those are equal, replaces the former with desired
(performs read-modify-write operation). Otherwise, loads the actual
value stored in *this into expected (performs load operation).
As you see, otherwise the actual value of head is loaded into expected.

Linked List Class in MATLAB - Insert node manually without insertAfter()

I am trying to use the Linked List Class implementation in MATLAB.
Now, it says the only way to insert a node into the list is by using insertBefore() or insertAfter().
But I want to insert the node manually, by specifying the Next value of the new node, like
newnode = dlnode(new);
ptr.Next = newnode;
newnode.Next=ptrnxt;
Would this work? I cannot use the insertBefore() or insertAfter() in my particular application since I am not maintaining a pointer of the current node.
Details regarding the linked list class is given here.
No, I don't think that would work with just those three lines of code because it ignores all the other logic that occurs to make sure that the Next and Prev are set for newnode and ignores the update to ptrnxt that would need to occur so that its Prev is now newnode. (And the Next property is private so you would have to change that to public…)
It is unclear by what you mean with I cannot use the insertBefore() or insertAfter() in my particular application since I am not maintaining a pointer of the current node. Yet you have the nodes that you want to insert newnode between? I'm guessing that the order of your nodes (prior to the insertion of the new one) is …,ptr,ptrnxt,…. Then why not just use
newnode.insertAfter(ptr);
which would change the order to …,ptr,newnode,ptrnxt,… and all three properties for each node would be set correctly/automatically.
Else, you would have to change your code to something like
newnode = dlnode(new);
ptr.Next = newnode;
newnode.Prev = ptr; % to make sure that newnode points back to ptr
newnode.Next = ptrnxt;
ptrnxt.Prev = newnode; % to make sure that ptrnxt points back to newnode
Much easier and safer to use the insertAfter and insertBefore methods.

pushing back an boost::ptr_vector<...>::iterator in another boost::ptr_vector?

I have the following code (just typed it in here, might have typos or stuff):
typedef boost::ptr_vector<SomeClass> tvec;
tvec v;
// ... fill v ...
tvec vsnap;
for(tvec::iterator it = v.begin(); it != v.end(); ++it)
{
if((*v).anyCondition)
vsnap.push_back( it ); // (*it) or &(*it) doesn't work
}
My problem is now that i cant push_back an iterator in any way, I just don't get the pointer out of the iterator.
Is there an easy way i didnt see, or are boosts ptr_vector the false choice for this case?
Thanks in advance.
Dereferencing a ptr_vector::iterator gives you a reference. Then you can use & to get the address of that reference, so vsnap.push_back(&(*it)) should compile. What error are you getting?
Besides, note that your usage is incorrect. The old ptr_vector owns the object, no matter what you do with the object's address. So with your code you'd have two ptr_vectors owning the same object. Then they would both try to delete it, and you'd crash. You probably want to transfer ownership instead:
vsnap.push_back(v.release(it));
Of course, this removes the object from the old vector before adding it to the new one. If you want the object to stay in both vectors, you can use std::vector or std::vector >. Another alternative is to keep the first one a boost::ptr_vector but make the second one a std::vector that owns nothing and just points to objects in the original vector. Then you would have to be careful with lifetimes.
You need to clone the objects held by the first vector:
for(tvec::iterator it = v.begin(); it != v.end(); ++it)
{
if((*v).anyCondition)
vsnap.push_back(new_clone(*it));
}

Resources