I have a an object that will potentially end up in multiple lists.
For example
std::list<object*> lista = new std::list<object*>();
std::list<object*> listb = new std::list<object*>();
object* obj = new object();
lista->push_front(obj);
listb->push_front(obj);
Potentially, there are many objects that will end up in both lists in the same way. I realize smart pointers would be the easy thing to do, but call me a masochist - I'd prefer to figure out how to do it without.
Currently, I'm trying this technique:
td::list<object*>::iterator iter;
for(iter = lista->begin(); iter != lista->end(); iter++) {
delete (*iter);
*iter = 0;
}
std::list<object*>::iterator iterB;
for(iterB = listb->begin(); iterB != listb->end(); iterB++) {
if(*iterB != 0) {
delete (*iterB);
*iter = 0;
}
}
delete lista;
delete listb;
But it breaks on my equivalent of delete lista; at run time. Hopefully someone out there smarter about pointers can help me out. Thanks in advance!
P.S. I'm running Windows 7/MinGW.
A main problem is that you (apparently, you do not offer complete code) delete an object twice: once when iterating through list A, and once when iterating through list B.
There are three main solutions:
Use a ref-counting smart pointer like std::shared_ptr.
Recommended. Your statement that you do not want to use a smart pointer seems to be made out of ignorance rather than some silly-manager's requirement.
Keep the nodes also in a primary list:
delete a node only when you know that the only list it's still in, is the primary list.
Implement a reference count yourself:
The easiest is again to use an existing library solution such as boost::intrusive_ptr, but all you have to do is to meticulously maintain a reference count in each node. delete when the reference count goes down to 0.
A fourth possibility is to use a garbage collector such as the Boehm collector, but then the code needs to be structured to support it. Or at least that's my impression. And it may be difficult to get help with that, since very few C++ programmers use that approach (which indicates that it's not entirely free of problems).
Use shared_ptr or have a master list with unique_ptr.
Failing that, have a master list that owns the pointers, and delete from it after you clear but do not delete all other lists.
Failing that, do not directly delete from a list directly. Instead insert the pointers you want gone into a std::set, and either remove them from the other lists before deleting (iterate and find in the set), or accumulate all the pointers you want to dispose of then mass delete them from the set.
This is in rough order of suckitude by paragraph.
Not sure why you don't really want to use shared_ptr. Ok suit yourself. How about you just create a local shared_ptr? If not then load both the list into one master list. Clear the two sublist, and delete each element in the master list as well as clearing the master list.
In the line
if(*iterB != 0) {
*iterB will never be 0. So you are double deleting.
Add counter field to your object. Default initialize to 0. Add +1 on adding to a list. -1 on removal from a list. If counter==0, delete the object.
This is not thread safe as shared_ptr, but it can be much faster for the same reason.
Related
I have a set of unique pointers pointing to objects. Occasionally, I will reveal some of the raw pointers to these objects so other parts of the code can do stuff with the objects. This code does not know whether the pointers are pointing to objects maintained by a certain set of unique pointers or not, so I need to check whether the object pointed to by a pointer is in a unique pointer set.
In simple code:
int* x = new int(42);
std::set<std::unique_ptr<int>> numbers;
numbers.insert(std::unique_ptr<int>(x));
numbers.find(x) // does not compile
I understand why the code does not compile, but I cannot think of a way to search for the element with the STL. Is there anything that caters to my needs or will I have to iterate over all elements of the set manually?
You can use std::find_if like this:
std::find_if(numbers.begin(), numbers.end(), [&](std::unique_ptr<int>& p) { return p.get() == x;});
Why not use boost::ptr_set instead?
I am not very good with STL and I saw few post similar to my requirement and got confused. So, I need some suggestion on following code.
SomeStruct someStruct(identifier);
std::vector<SomeStruct*>::iterator it = std::find_if(vWrapper.begin(), vWrapper.end(), SomeStruct::Find_SomeStruct(&someStruct));
if(it != vWrapper.end())
{
...
delete *it;
it = vWrapper.erase(it);
}
I am trying to peek into vector based on identifier and then delete pointer to object stored in vector.
I saw the post. It makes use of for loop and reassigns the iterators. Also, none of the post has used find_if() then delete and erase.
Am I doing it the right way?
Formally, what you're doing is undefined behavior, but practically
speaking, it's fine. The undefined behavior occurs because
std::vector requires that all of its contents be copiable and
assignable, at all times, and delete makes the pointer value it was
passed invalid, and thus uncopiable. In practice: std::vector isn't
going to copy the pointer value if you erase it immediately after, and I
don't know of a machine today where a deleted pointer value can't really
be copied without risk. (Just don't dereference it.) If you really
want to avoid the undefined behavior, you can do something like:
SomeStruct* tmp = *it;
it = vWrapper.erase(it);
delete tmp;
but frankly, I'm not sure it's worth the effort.
That invokes undefined behavior. For explanation, read #James Kanze's answer.
I would rather move to next question: if in the other topic, none of the answer have used std::find_if, then it is because those posts do not talk about deleting and erasing a particular element. They
seem to delete all the elements, or few of them have used functor where they check which objects to delete, which is also fine.
But the major difference between your code, and their code is that your code deletes and erases at most one object, and their code could delete all objects (the one which uses functor and inside the functor it deletes the object on meeting the condition).
Well this is what I could say for a correctly written std::find_if.
However, in reality, I couldn't understand your code, especially these two lines:
//I formatted the code so that entire code is visible without
//scrolling horizontally
SomeStruct someStruct(identifier);
std::vector<SomeStruct*>::iterator it = std::find_if
(
vWrapper.begin(),
vWrapper.end(),
SomeStruct::Find_SomeStruct(&identifier)
);
What is the first line doing there? You declared a variable and forgot it? Well maybe, you use it somewhere else; in that case, it is okay.
But what is SomeStruct::Find_SomeStruct? Is it a nested class which can act like a functor? a static function or what? Does your compile successfully? A complete answer also depends on these questions which I posed.
Personally, I do not have raw pointers in a container, not to deal with problems that you ask. I do not think to choose the right way to delete them. Use a smart pointer, like std::shared_ptr, instead, and it will delete its raw pointer it owns, when the smart pointer goes out of the scope by RAII.
So instead of
std::vector<SomeStruct*> vec;
, use
std::vector<std::shared_ptr<SomeStruct>> vec;
So how about deleting an item?
vec.erase(std::remove_if( vec.begin(), vec.end(),
[&vec]( std::shared_ptr<SomeStruct> & item )
{
bool condition = // The condition on which the item will de deleted. e.g. item->x == 0;
return condition;
}
),vec.end());
I'm currently trying to implement the A* pathfinding algorithm using C++.
I'm having some problems with pointers... I usually find a way to avoid using them but now I guess I have to use them.
So let's say I have a "node" class(not related to A*) implemented like this:
class Node
{
public:
int x;
Node *parent;
Node(int _x, Node *_parent)
: x(_x), parent(_parent)
{ }
bool operator==(const Node &rhs)
{
return x == rhs.x && parent == rhs.parent;
}
};
It has a value (in this case, int x) and a parent (a pointer to another node) used to navigate through nodes with the parent pointers.
Now, I want to have a list of nodes which contains all the nodes that have been or are being considered. It would look like this:
std::vector<Node> nodes;
I want a list that contains pointers pointing to nodes inside the nodes list.
Declared like this:
std::vector<Node*> list;
However, I'm definitely not understanding pointers properly because my code won't work.
Here's the code I'm talking about:
std::vector<Node> nodes;//nodes that have been considered
std::vector<Node*> list;//pointers to nodes insided the nodes list.
Node node1(1, NULL);//create a node with a x value of 1 and no parent
Node node2(2, &node1);//create a node with a x value of 2 and node1 being its parent
nodes.push_back(node1);
list.push_back(&nodes[0]);
//so far it works
//as soon as I add node2 to nodes, the pointer in "list" points to an object with
//strange data, with a x value of -17891602 and a parent 0xfeeefeee
nodes.push_back(node2);
list.push_back(&nodes[1]);
There is clearly undefined behaviour going on, but I can't manage to see where.
Could somebody please show me where my lack of understanding of pointers breaks this code and why?
So, the first issue that you have here is that you are using the address of individual Nodes of one of your vectors. But, over time, as you add more Node objects to your vector, those pointers may become invalid, because the vector may move the Nodes.
(The vector starts out at a certain pre-allocated size, and when you fill it up, it allocates a new, larger storage area and moves all of the elements to the new location. I'm betting that in your case, as soon as you add the second Node to nodes, it is doing this move.)
Is there a reason why you can't store the indices instead of the raw pointers?
One problem is that push_back can force a reallocation of the vector, i.e. it creates a larger block of memory, copies all existing elements to that larger block, and then deletes the old block. That invalidates any pointers you have to elements in the vector.
The problem is that, every time you add to a vector, it might need to expand its internal memory. If it does so, it allocates a new piece of storage, copies everything over, and deletes the old one, invalidating iterators and pointers to all of its objects.
As solution to your problem you could either
avoid reallocation by reserving enough space upfront (nodes.reserve(42))
turn nodes into a std::list (which doesn't invalidate iterators or pointers to elements not directly affected by changes)
store indexes instead of pointers.
Besides your problem, but still worth mentioning:
The legal use of identifiers starting with underlines is rather limited. Yours is legal, but if you don't know the exact rules, you might want to avoid using them.
Your comparison operator doesn't tell that it won't change its left argument. Also, operators treating their operands equally (i.e. not modifying them, as opposed to, say, +=), are usually best implemented as free functions, rather than as member functions.
just adding to the existing answers; instead of the raw pointers, consider using some form of smart pointer, for example, if boost is available, consider shared_ptr.
std::vector<boost::shared_ptr<Node> > nodes;
and
std::list<boost::shared_ptr<Node> > list;
Hence, you only need to create a single instance of Node, and it is "managed" for you. Inside the Node class, you have the option of a shared_ptr for parent (if you want to ensure that the parent Node does not get cleaned up till all child nodes are removed, or you can make that a weak_ptr.
Using shared pointers may also help alleviate problems where you want to store "handles" in multiple containers (i.e. you don't necessarily need to worry about ownership - as long as all references are removed, then the object will get cleaned up).
Your code looks fine to me, but remember that when nodes goes out of scope, list becomes invalid.
Say I have two classes created work and workItem.
CWorker *work = new CWorker();
CWorkItem *workItem = new CWorkItem();
The work class has a public list m_WorkList and I add the work item to it.
work->m_WorkList.push_back(workItem);
If I just delete work
if(work != NULL)
delete work;
Do I need to loop through the list in the destructor like the following? Any better way to do this? Could I use clear instead?
while(m_WorkList.size())
{
CWorkItem *workItem = m_WorkList.front();
m_WorkList.pop_front();
if(workItem)
delete workItem;
}
Yes you need to delete each item. If you call new N times, then you need to call delete exactly N times as well. There is no shortcut for bulk deleting items.
Also when you're done with it you need to call delete on work.
You can use new[] and delete[] if you want to create an array of items on the heap and release the items on the heap respectively at once. But in your case this isn't what you're looking for.
You can look to boost::shared_ptr if you don't want to manually do these delete calls.
as said in the other responses, you need to loop over your list and delete each elements. if you call clear, it will just remove pointers from the list not pointed objects.
if you need a list with the notion of ownership you can use boost pointer container. it will ensure that your objects are destroyed when you destroy your list
Assuming that you don't maintain a list of workItems elsewhere, then yes, you'll need to delete each of them individually before you delete the Worker itself (thus losing the references). If the Worker holds the only list, then the deconstructor is as good a place as any (otherwise you'll need to delete each workItem "manually" before you call delete on the Worker itself)
However, if the workItems references exist elsewhere, you can choose the appropriate time to delete them, which may or may not be when you delete Worker.
As others have said, you need a delete with every new. The container won't do this for you by default. You don't need to pop the items off the list though. You can create a functor to do the work for you. The following is common practice for people who can't use tr1::shared_ptr or Boost.
struct deleter
{
template <class T>
void operator()(const T* ptr) const
{
delete ptr;
}
};
// Usage
std::for_each(work->m_WorkList.begin(), work->m_WorkList.end(), deleter());
delete work;
It really depends on the ownership, which is what you need to decide on when building the interface. Say you have a method:
CWorker::AddItem(CWorkItem *workItem)
You need to specify who owns the memory, and therefor who should delete it. Depending on what you are trying to do, it could make sense for the caller to own it (like if items should be routinely shared between CWorkers), or for the CWorker to own it (if each CWorkItem belongs to a single CWorker). Whoever owns it is responsible for deleting it.
In the former case, you could take the the WorkItems as shared_ptrs, to specify the ownership is shared between Workers, and you wouldn't need to do manual deletes. In the latter case, you could also use a specialized container like ptr_vector to obviate the need for manual deletes, but you should also but a note on the function that you are taking control of the memory.
Also, as a note, delete is null-safe, so you don't need those if statements, and it would be faster to pop_back() than pop_front()
use boost shared_ptr (which will soon become a standard)
typedef boost::shared_ptr<WorkItem> WorkItemPtr;
....
std::list<WorkItemPtr> list;
...
list.push_back(new WorkItem);
Now when list is deleted the WorkItems will be deleted for you. You can pass WorkItemPtrs around in your code and not have to worry about them.
How could I free up a linked list that contains dynamically allocated objects?
I try to use list<class*> lists, but then I could not use the insert() function to insert object to the list. Does anyone know what is the cause?
std::list<boost::shared_ptr<YourType> > will automatically call YourType::~YourType on each (smart) pointer in the list, when the list is deleted. And if you erase one list element, it will call YourType::~YourType for that one element. You can still call list.insert(new YourType)
Link: www.boost.org
how could I free up linked list that contain dynamically allocated object?
Walk the list, deleting the contained object for each link, or better in some cases, write a link dtor that deletes the contained object.
I try to use list lists, but then I could not use insert()function to insert object to the list. Does anyone know what is the cause?
Not without seeing your code.
Traverse the list from the beginning to end, and delete one by one.
The solution used by the STL is to have the container own the objects it contains. In this scenario each node would be responsible for deallocating it's object when it's destructor is called. You're still responsible for deallocating the copy of the object you pass in.
Edit
If you're attempting to use the stl List and encountering an error, it might be the case that the object you're trying to place inside does not implement a copy constructor. This can happen if you try to stick things other than pointers into the list. If you're comfortable with pointers you might consider storing them in your containers instead of the objects themselves. This will require that you call 'delete' yourself on the pointer when you're done with it. This is typically done by calling 'delete' on the pointer contained in a node when you remove it or by walking the list when you're done with it and calling 'delete' on the contents of each node.
You will have to iterate the list and delete the dynamically allocated objects, before clearing the list.
When using containers of newed
pointers, please remember to delete
the pointers before the container is
destroyed.
About problem using insert() : I am not very sure what is the problem you are facing. From the explanation, I assume, you are trying to insert objects of Class into list where as the list contains the pointer to Class. Could you please elaborate the problem with insert?
Pseudo code for deleting the dynamically allocated objects:
version 1: Simple
list<Class*>::const_iterator iter = m_ClassList.begin();
list<Class*>::const_iterator endIter = m_ClassList.end();
for(;iter!= endIter ; ++iter)
{
delete *iter;
}
ClassList.clear();
version 2: A better version using for_each
struct DeleteClassObject
{
//Functor
template<typename T>
void operator()(const T* ptr) const
{
delete ptr;
}
}
//loops through list and deletes the dynamically allocated objects using
//functor DeleteClassObject
for_each( m_ClassList.begin(), m_ClassList.end(), DeleteClassObject ());
DeleteClassObject.clear()
You could use ptr_list from Boost
http://www.boost.org/doc/libs/1_38_0/libs/ptr_container/doc/ptr_list.html
EDIT: THIS IS WRONG, SORRY
If you're using std::list then there's a clear function to delete all objects you put in.
std::list test;
test.clear();
Oh, and .clear() also invokes the destructors.
To use the insert function of such lists you need to specify the position via an iterator.
test.insert(test.end(), 5);
But there's more than 1 insert function, here you can find more details
EDIT
Could somebody leave a comment when downvoting?
Start your project in language/environment, which having an automatic memory management (Garbage collection). Then things like that will be the least which you care about. It will save your time to put your efforts into something else.