1

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.

Cœur
  • 37,241
  • 25
  • 195
  • 267
  • unique_ptr cannot be copied. Try shared_ptr. – Paul Rooney Jan 29 '15 at 12:26
  • @user0175554 What is `AllocateA`? Please tell me that's not what you named your deleter. – Jonathan Mee Jan 29 '15 at 13:07
  • You can't have a copy constructor if you want to *transfer* ownership. A copying operation should leave the original unmodified. – molbdnilo Jan 29 '15 at 13:15
  • @user015554: as the other said: you cannot copy `unique_ptr` but you can `move` it :) – Michał Walenciak Jan 29 '15 at 13:21
  • @MichałWalenciak I'm sure that you're implying this, but just for clarity: Do **not** `move` a member variable in a copy constructor. Do that in a move constructor. – Jonathan Mee Jan 29 '15 at 13:25
  • 1
    Why does the title of your question refer to shared pointers? `unique_ptr` is not the same as `shared_ptr` – Jonathan Wakely Jan 29 '15 at 14:00
  • 1
    Your copy constructor and assignment operator should take `const B&` parameters. – Jonathan Wakely Jan 29 '15 at 14:03
  • @JonathanMee Why is it ? – user0175554 Jan 29 '15 at 14:48
  • @user0175554 Why is `AllocateA` a deleter? Cause it's your second template argument to a `unique_ptr`: http://www.cplusplus.com/reference/memory/unique_ptr/#parameters I'm wondering if you didn't intend `AllocateA` to be the second template argument to the `vector` in your `BVEC` `typedef` as `vector` actually does take an allocator as the second template parameter. – Jonathan Mee Jan 29 '15 at 15:02

2 Answers2

2

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

David Haim
  • 25,446
  • 3
  • 44
  • 78
0

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.

Community
  • 1
  • 1
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • 1
    Thank you, without the AllocateA, my program won't work. I use shared_ptr plus your code but I also agree that your answer is correct except my own case. – user0175554 Jan 29 '15 at 16:44