user0175554
user0175554

Reputation: 53

Transferring Ownership in vector of unique_ptrs

I have 2 classes A and B

//A.h
class A{};

// B.h
typedef unique_ptr<A, AllocateA> APtr;
typedef vector<APtr> BVEC;

class B
{
public:
   BVEC vec; //error is here
   //....
};

When I compile the code I get unique_ptr....attempting to reference a deleted function

I then add a copy contructor and an assignment operator to the B class like this

class B
{
public:
   BVEC vec; //error is here
   //....
   B& operator=(B&b);
   B(B&b);
};

But I still get the same error message.

Upvotes: 1

Views: 284

Answers (2)

Jonathan Mee
Jonathan Mee

Reputation: 38919

This code runs fine on both gcc 4.9.2 and Visual Studio 2013:

#include <iostream>
#include <memory>
#include <vector>
#include <algorithm>

using namespace std;

//A.h
class A{
public:
    int alpha;
    A(int input) : alpha(input){}
};

// B.h
typedef unique_ptr<A> APtr;
typedef vector<APtr> BVEC;

class B
{
public:
    BVEC vec;
    B(){}
    const B& operator=(const B& b){
        vec.clear();
        for_each(b.vec.cbegin(), b.vec.cend(), [&](const unique_ptr<A>& i){vec.push_back(unique_ptr<A>(new A(*i))); });
        return b;
    }
    B(const B& b){
        vec.clear();
        for_each(b.vec.cbegin(), b.vec.cend(), [&](const unique_ptr<A>& i){vec.push_back(unique_ptr<A>(new A(*i))); });
    }
    const B& operator=(B&& b){
        vec.resize(b.vec.size());
        move(b.vec.begin(), b.vec.end(), vec.begin());
        return *this;
    }
    B(B&& b){
        vec.resize(b.vec.size());
        move(b.vec.begin(), b.vec.end(), vec.begin());
    }
};

int main() {
    B foo;
    B bar;

    for (auto i = 0; i < 10; ++i){
        foo.vec.push_back(unique_ptr<A>(new A(i)));
    }
    bar = foo;
    foo.vec.clear();

    for (auto& i : bar.vec){
        cout << i->alpha << endl;
    }
    foo = move(bar);

    for (auto& i : foo.vec){
        cout << i->alpha << endl;
    }
    return 0;
}

I don't know what you used for your deleter in APtr. (I've asked the question in the comments, but haven't seen a response yet.) I suspect that if you wrote your copy constructor for B and your copy constructor for A correctly then your problem is with your deleter, AllocateA.

You can see in the copy constructors that I wrote for B that I dynamically create an identical A in this.vec for each A in b.vec. I assume that's the behavior that you want. If you want to just move the dynamic allocations over I would suggest using a move constructor as suggested by Michal Walenciak.

EDIT: After reviewing the OP's title I felt that what may have been intended was a move constructor. So I've added one of those as well.

Upvotes: 0

David Haim
David Haim

Reputation: 26496

That's because unique_ptr are ... unique, the whole point that they point to an object and when the unique_ptr gets out of scope - it deletes the variable it points at. if you could easly assign the pointed variable to another unique_ptr, when will the pointed variable will be deleted? when the first gets out of scope or the second on? there is no "uniqueness" here.

that is why copying or assigning unique_ptr is not allowed , the copy ctor and the assignment operator are disabled

you're looking for shared_ptr . multiple shared_ptr can point at one variable, and it gets deleted when ALL of them get out of scope , some sort of primitive-garbage collector

Upvotes: 2

Related Questions