I am working on C++ STL recently, and I will discuss an example using deque
. Note that deque
is just an example, we could also use vector
or others.
Background
The minimal reproducible example is a simple multi-queue producer-consumer problem. Consider a smart washer who can do the laundry itself, and a smart dryer who can take the clothes from the washer and dry them. The washer can be considered a queue of multiple unwashed clothes, while the dryer can be considered as a queue of washed clothes.
Let class Clothes
be a unit of clothes. The producer will keep generating Clothes
and add them to the washer queue. When the washer finishes one Clothes
, it will remove it and add it to the dryer queue.
Question
If we were to do this in C, it would be simple by using pointers (malloc()
) and a linked list. By moving the pointers around we are guaranteed that no duplicated Clothes
are allocated. When we finished, we could simply call free()
.
Can we do the same thing in C++ STL? What would be the recommended approach to achieve that?
What I have tried and what makes me confused
I ran some tests and found that C++ STL handles the memory allocation and deallocation itself, which makes me really confused.
For instance, (suppose we use deque
in this case):
std::deque<Clothes> washer = {...}; // only 1 object
std::deque<Clothes> dryer; // empty
// case 1: copy constructor is invoked, 2 memory locations occupied
Clothes c = washer.front();
washer.pop_front(); // destructor is invoked, I think this corresponds to the original Clothes
The above invokes the copy constructor and results in 1 duplicated copy. The operation pop_front()
implicitly invokes the destructor of the Clothes
object. But it will not influence c
as it is constructed by the copy constructor. Now, the number of Clothes
is still one.
// case 2: copy constructor is not invoked
Clothes &c = washer.front();
washer.pop_front(); // destructor is invoked again, but there is only one Clothes object
The above code obtains the first object in washer
by reference, and the copy constructor is not invoked. I would assume that there is still only one Clothes
object now. However, when we call pop_front()
, the destructor of Clothes
is invoked. I tried to access some fields in Clothes
object by c.val
(suppose val
is a field in Clothes
), and I found that I could still get access to it, meaning Clothes c
was not destructed. That is why I am confused. Why is the destructor invoked, and which Clothes
object was destructed?
My thoughts
I think case 1 is likely to be the correct approach, but case 2 seems to be correct as well, although some unexpected things happened.