Deallocating std::list without going out of scope - c++

In STL one of the ways to create a dynamically allocated array is to create a list. When lists go out of scope destructor for every element is called and the list is deleted. Is there a way to destroy list (and more importantly release the memory used) before list going out of scope, and if it's possible then what is the best way to do it? Will delete[] or list::clear() do the job?

In STL one of the ways to create a dynamically allocated array is to create a list.
Linked lists and arrays are quite different data structures.
Is there a way to destroy list (and more importantly release the memory used) before list going out of scope
You can erase all elements of std::list, or any other standard container (excluding std::array) using the clear member function. All standard containers except for std::vector and std::basic_string release the memory allocated for elements when they are erased in practice. You may achieve the same with vector and string using shrink_to_fit after clearing.
Alternatively, it may be a good idea to make the scope of the list smaller instead.
Will delete[] ... do the job?
No. delete[] may be used only with pointers to first element of array created using an allocating new-expression. std::list is not a pointer created using an allocating new-expression. You may not use delete[] on a std::list.

Related

C++ When to use pointer to vector?

I have a problem about pointer and standard library use.
Let's create a new class
class Graph
{
std::vector<Edge> *edge_list;
//another way is
//std::vector<Edge> edge_list;
}
I already thought two reasons why I use pointer:
It's easy to manipulate the memory using new and delete
It can be passed by parameters easily.
However, we can pass by reference if we use vector.Then Reason 2 doesn't count.
So, Is it true if I am not strict with memory allocation, I don't need to use pointer to vector and other std container?
The implementation of std::vector contains 2 pointers:
The beginning of the allocated array
1 element after the end of the allocated array
Essentially, when you declare a vector it has no space allocated in the heap, but as you add elements this changes.
Note that std::vector manages the memory it uses, so there is no need for you to worry about new and delete (unnecessary complexity). As soon as it goes out of scope, it deallocates its memory (stack and heap).
As you said, a vector can be passed very easily by reference, which works the same way as a pointer for machine code, and it's more clear.

vector of pointer

I just wonder what's wrong with vector of pointer. some of my friend recommend me to use list instead of vector. will this cause a problem:
vector<Fruit*> basket;
basket.push_back(new Apple());
basket.push_back(new Orange());
vector<Fruit*> temp;
temp.push_back(basket[1]);
If I delete vector temp, do I destroy the basket[1] object too? if not, what's the problem with using vector of pointer?
If I delete vector temp, do I destroy the basket[1] object too?
No. First of all, you cannot delete temp; rather, it will get destroyed when going out of scope. And when this happens, the objects pointed by elements of the vector won't be automatically deleted.
This is, however, not a specific problem of vector: using list will not save you from this issue. The problem is rather with raw pointers. If you want the pointed objects to be automatically deallocated when the the lifetime of the last pointer which points to it ends, you should use smart pointers.
Depending on the ownership policy that your application needs, you might choose between shared_ptr and unique_ptr. The caveat with shared_ptr is that referencing cycles shall be avoided, to prevent mutually referencing objects from keeping each other alive. You may want to check weak_ptr in this respect.
Finally, unless you have a good reason for not using vector, vector should be the default choice for a container. From Paragraph 23.2.3/2 of the C++11 Standard:
The sequence containers offer the programmer different complexity trade-offs and should be used accordingly. vector or array is the type of sequence container that should be used by default. list or forward_list should be used when there are frequent insertions and deletions from the middle of the sequence. deque is the data structure of choice when most insertions and deletions take place at the beginning or at the end of the sequence.
If either of the vectors, basket or temp, are destroyed none of the Fruits are destroyed. Anything that is dynamically allocated with new must be deleted. When the vectors go out of scope, they do not delete the objects that are pointed to by their elements. If you delete an object through one vector that is pointed to in the other vector, both point at the now deleted object.
Since your vectors have automatic storage duration, you definitely must not do delete basket; or delete temp;.
It's not recommended to use raw pointers in general, especially with dynamically allocated storage that you may forget to delete. In this case, however, you do need polymorphic behaviour, which is provided by pointers. You should use a smart pointer to avoid the problems with raw pointers. Try a std::vector<std::shared_ptr<Fruit>>.

Splitting QList into chunks, pointers or references?

I have this application that requires me to have a QList which will contain 1 < x < 10000+ objects. Now I have a few issues.
First of all, should I declare the QList as a pointer or straight on the stack? The objects in the QList are pretty small and are wrappers for QFileInfo. But how should I do this?
A list of objects on the stack?
A list (on stack) of pointers to objects on the heap?
A..
QList<FileInfoWrapper>*
Firstly, if I picked solution 2, would my heap be a mess since I just allocate small portions of data all over the place? I dont want that.
Secondly, if I pick the 3rd solution, how would this look in memory when I access the individual objects? And could I create pointers to them (they are afterall on the heap)?
Then we come to my other issue. This list will be past around like a fork at a diner and at some point I would like to create sublists that doesn't hold any data, only references/pointers to some of the objects in the list(for example object 0 to 250). I will then throw these lists into different threads that will have to have a ref to the object to be able to edit them (read: not a hard copy).
Also, could someone explain exactly what happens on the heap when you create a list like this:
QList<FileInfoWrapper>* list = new QList<FileInfoWrapper>();
Would it be like in c where you just create a pointer to the offset where that object will be located?
*(list + sizeof(FileInfoWrapper) * 10)
QList is a container class ... that means that it manages the memory for you so you don't have to worry about it. It's underlying data-structure is a variant of a deque with some special modifications, so your understanding of indexing into the list is not correct. But either way, these are details that are abstracted away by the interface, and you don't need to worry about them. You simply use the given class methods like operator[] or at() to obtain a reference to an object at a given index, and other functions like push_back() or insert() to copy objects into the container. So you can simply make a QList instance on the stack (as long as it doesn't go out-of-scope while it's needed), and copy objects into it. The underlying data-structure will properly allocate the memory needed dynamically to store the objects, and at the time of destruction of the QList object, it will deallocate the memory used to store the objects it "owns".
Think about QList as you would think of a STL container like std::vector or std::list ... again, the underlying data-structure for QList is not the same as these STL containers, but the point is that you can allocate the data-structure on the stack like you would any other class, and it contains all the private data-members and information necessary to manage the memory on the heap. Allocating the QList on the heap through a call to new doesn't gain you anything in that regard ... there are already pointers, etc. inside the data-structure allocating and managing the memory of the contained objects for you.
Finally, don't worry about data-fragmentation. The point of a good container class is to properly allocate memory to avoid memory fragmentation issues from allocating and reallocating memory too often. Additionally, allocating memory takes time, so if a container class were to constantly need to call new, that would really hurt it's performance. While allocating memory on every insertion may be a necessity for node-based containers like linked-lists and trees, hash-tables, dynamic-arrays, and other block-type data-structures are much more efficient at utilizing the memory they allocate to minimize these allocation calls.

About a vector defined in a function

Suppose a std::vector is defined in a function (i.e., on stack) and the vector is re-allocated (like by inserting data). Will any part of the vector be in heap? if yes, will it leave any garbage in heap when done executing the function? Thanks.
Will any part of the vector be in heap?
Yes: all of the elements in a std::vector are stored in a heap-allocated array.
Will it leave any garbage in heap when done executing the function?
No. The std::vector container, like all of the Standard Library containers, is responsible for cleaning up any objects that it creates.
Note, however, that if you dynamically allocate objects (e.g., using new) and store them in a container, then you are responsible for destroying those objects. To avoid having to clean things up yourself, you should avoid explicitly dynamically allocating objects wherever possible and use smart pointers everywhere else.

STL vector deallocation

Given an STL vector of pointers, each element has to be deallocated before destroying the vector itself. Is there any technical implication that prevents the STL library for doing it automatically?
Thanks
The reason the STL doesn't do it for you is that it can't know whether or not it's supposed to. You might have a vector of pointers to arrays (in which case it needs to do delete[]), of pointers to regular objects (in which case it would need to do delete), or possibly memory from some custom allocator. Those pointers could also be shared with some other objects, in which case deleting them would cause those other objects to point at garbage data, leading to undefined behavior. Those pointers could also be to stack-allocated memory, in which case no deallocation is necessary.
you can store there pointers that shouldn't be deleted when vector is destructed
use vector of smart pointer (e.g. boost::shared_ptr) to receive automatic deallocation
If a vector contains pointers, it does not mean that the pointers point to dynamic memory. And if they do, should delete or delete[] be applied to each pointer? And what if the pointers points to objects created using placement new? All these question should be answered by the programmer, not by the library.