chrise chrise - 16 days ago 6
C++ Question

moving unique pointers between deques

I have a container class for some unique pointers to objects.

I now need to take one of them, do something with them in a different class and hand over to another class (and at some point recycle them and put them back to the container ).

Below is the outline of the code. However I am getting confused with the right way to move unique pointers with functions:

using uptrPod = unique_ptr<Pod>;
using dqUptrPods = deque<uptrPods>;

class Container {
public:
Container() :
n_elements_( 500 )
{
for ( auto i = 0; i < n_elements_; i++ ) {
free_pods_.push_back( uptrPod( new Pod()) );
}

const uptrPod&& getPod() {
auto up_pod= std::move( free_pods_[0] );
free_pods_.erase( free_pods_.begin() );
return up_pod;
}

void returnPod( const uptrPod&& up_pod ) {
free_pods_.push_back( up_pod );
}

private:
long n_elements_;
dqUptrPods free_pods_;
};

class PodTracker {

void addPod( const uptrPod&& up_pod ) { dq_pods_.pushback( up_pod ); }
dqUptrPods dq_pods_;
};

class PodHandler {

void movePod() {
up_pod = std::move( container_->getPod() );

/// do stuff with pod

pod_tracker_->addPod( up_pod );
}

Container* container_;
PodTracker* pod_tracker_;
};


I am getting the error:


cannot bind std::unique_ptr l value to const uptrPod&& { aka const std::unique_ptr &&


How can I hand around the pointer between the classes?

Answer

Pass/return the std::unique_ptr instances by value, and explicitly use std::move:

uptrPod getPod() { 
    auto up_pod= std::move( free_pods_[0] ); 
    free_pods_.erase( free_pods_.begin() );
    return up_pod;
}

void returnPod( uptrPod up_pod ) { 
    free_pods_.push_back( std::move(up_pod) );        
}

class PodTracker{
    void addPod(uptrPod up_pod) { dq_pods_.push_back(std::move(up_pod)); }
    dqSptrPods dq_pods_;
};

void movePod() {

    // `std::move` is not necessary here, as `getPod()`
    // is already a temporary (rvalue)
    auto up_pod = container_->getPod();

    /// do stuff with pod

    pod_tracker_->addPod( std::move(up_pod) ) ;   
}

example on wandbox


Note that const rvalue references do not make much sense - an rvalue reference.

The main purpose of rvalue references is to allow us to move objects instead of copying them. And moving the state of an object implies modification. As a result, the canonical signatures for the move constructor and the move assignment operator both take its argument as a non-const rvalue reference.

(From: "What are const rvalue references good for?")