Search code examples
c++pass-by-referencedeque

C++: how to properly pass a variable returned by deque::front() out of a function?


I am working on a multithreading program where a "std::deque< MyObject > myBuffer" is used as a FIFO buffer, a producer thread is constantly adding custom objects to the end of a deque using push_back(), and a consumer thread uses a helper function to retrieve the object and handle the synchronization and mutex.

std::deque< MyObject > myBuffer;
std::mutex mtx;

int main() {
    std::thread producerThread(producer());
    std::thread consumerThread(consumer());

    // other code

    return 0;
}

The producer function:

void producer() {
    while (somecondition) {

        // code producing MyObject object

        std::lock_guard<std::mutex> lck(mtx);
        myBuffer.push_back(object);
    }
}

The consumer function:

void consumer() {
    while(somecondition) {
        MyObject object1, object2;
        if (retrieve(object1)) {
            // process object1
        }
        if (retrieve(object2)) {
            // process object2
        }
    }
}

My current helper function looks like this:

bool retrieve(MyObject & object) {
    // other code ...
    std::lock_guard<std::mutex> lck(mtx);
    if (!myBuffer.empty()) {
        object = myBuffer.front();
        myBuffer.pop_front();
        return true;
    } else {
        return false;
    }
}

However, I quickly realized that deque::front() returns the reference of the first element in the container. And "object" is MyObject&, so based on my understanding, only the reference of the first element in the deque is passed to object and as a result when I call the pop_front(), the element referenced should be gone and the object variable is holding an invalid reference. Surprisingly, when I actually ran the code, everything worked as opposed to what I expected. So could anyone help me understand how this "deque::front() returns the reference" works? Thanks.


Solution

  • It works properly and this is expected behavior.

    You don't assign the reference - you can't, C++ references are immutable. You actually copy the value. This is how it is supposed to work. Semantic of foo = ... assignment when foo is a reference is roughly: "copy the right-hand value to the place referenced by foo".

    When there is a reference on the right side, the referenced value is copied.

    In your case, object = myBuffer.front(); line copies the front value of deque to variable object1 or object2 in consumer(), respectively to the call. Later call to .pop_front() destroys the value in the deque, but doesn't affect the already copied value.