vidanovicd
vidanovicd

Reputation: 21

Compilation error with unique_ptr

any idea why is this not compiling:

#include <iostream>
#include <vector>

class A {
public:
  A() : m_Member( 1 ) {
    std::cout << "Constructor called." << std::endl;
  }
  A( A const & t_a ) {
    m_Member = t_a.m_Member;
    std::cout << "Copy constructor called." << std::endl;
  }

  virtual ~A() {
    std::cout << "Destructor called." << std::endl;
    m_Member = 0;
  }
  void play() { std::cout << "Number is: " << m_Member << std::endl; }
private:
  int m_Member;
};

class B {
public:
  B() {
    std::cout << "Main object created!" << std::endl;
  }

  B( B & b ) {
    for( std::unique_ptr< A >& val: b.m_Array ) {
      m_Array.push_back( std::unique_ptr< A >( new A( *val ) ) );
    }
  }

  virtual ~B() {
    std::cout << "Main object destroyed!" << std::endl;
  }

  A& get( size_t const Index ) {
    return *m_Array[ Index ];
  }

  void add( A& a ) {
    m_Array.push_back( std::unique_ptr< A >( new A( a ) ) );
  }

private:
  std::vector< std::unique_ptr< A > > m_Array;
};

B createB() {
  B b;
  A a1;
  A a2;
  b.add( a1 );
  b.add( a2 );
  return b;
}

int main() {
  B b = createB();
  A& temp = b.get( 1 );
  temp.play();
  return 0;
}

I get this:

error: no matching constructor for initialization of 'B' B b = createB();

Also, for this example, is there a better way to keep vector of objects? Note that I intentionally created objects in a function so that objects passed to class B will be deleted before B is destroyed. Reference wrapper did not work in this case because it was pointing to object that was already deleted. I tried to solve that by introducing unique_ptr, but then I got this error.

Upvotes: 2

Views: 3102

Answers (2)

SloCompTech
SloCompTech

Reputation: 126

Manually create classes if you want to "move" them, then you can move pointers around. Because you have unmovable objects, you can't move them, but you can move their pointers,but you must allocate them manual with new or malloc so the object aren't deleted at the end of scope of function createB().

You manualy create class like this:

B *pointerToB = new B;

In your code:

B createB() {
    B *b = new B;
    A a1;
    A a2;
    b->add( a1 );
    b->add( a2 );
    return b;
}

int main() {
    B *b = createB();
    A& temp = b->get( 1 );
    temp.play();

    delete b; // Do not forget to delete manually allocated object !!
    return 0;
}

At the end you need to delete object with pointer:

delete pointerToB;

Upvotes: -1

AndyG
AndyG

Reputation: 41220

B is not copyable because it holds a std::vector<std::unique_ptr<A>> which is not copyable.

Your "copy constructor" is not actually a copy constructor. Change it to be this:

B(const B & b ) {
  for( const std::unique_ptr< A >& val: b.m_Array ) {
    m_Array.push_back( std::unique_ptr< A >( new A( *val ) ) );
  }
}
  • const B& b instead of B& b in the parameters
  • const std::unique_ptr<A>& val: instead of std::unique_ptr<A>& val:
  • Because the vector is not copyable, the compiler did not generate a copy constructor for B, and the type returned by createB as a temporary cannot be bound to a non-const reference.

Demo

Upvotes: 3

Related Questions