#include<iostream>
#include<memory>
#include<stdio>
using namespace std;
class YourClass
{
int y;
public:
YourClass(int x) {
y= x;
}
};
class MyClass
{
auto_ptr<YourClass> p;
public:
MyClass() //:p(new YourClass(10))
{
p= (auto_ptr<YourClass>)new YourClass(10);
}
MyClass( const MyClass &) : p(new YourClass(10)) {}
void show() {
//cout<<'\n'<<p; //Was not working hence commented
printf("%p\n",p);
}
};
int main() {
MyClass a;
a.show();
MyClass b=a;
cout<<'\n'<<"After copying";
a.show();//If I remove copy constructor from class this becomes NULL(the value of auto_ptr becomes NULL but if class has copy constructor it remains same(unchanged)
b.show();//expected bahavior with copy construcotr and withought copy constructor
}
Making the problem more specific:
Currently the class has copy constructor so there is no problem with the value of auto_ptr printed by a.show()(when it is called second time). It remians the same as it was when it was initiazed). It remians unchanged.
If I remove the copy contructor from the class MyClass , the value of auto_ptr printed by a.show()(when it is called second time) is NULL.
What's happening is due to the strange (but only justifiable if you think about it) semantics of assigning or copying an auto_ptr, e.g.
auto_ptr<T> a;
auto_ptr<T> b(new T());
a = b;
... or ...
auto_ptr<T> b(new T());
auto_ptr<T> a(b);
These will set a to b as expected, but they will also set b to NULL (see http://www.cplusplus.com/reference/std/memory/auto_ptr/auto_ptr/).
If you don't define a copy constructor for MyClass, then the compiler will generate one for you and will do just something similar to the above when it copies the auto_ptr member. Hence the copied from class will have a NULL member after the copy constructor has been called.
You shouldn't be casting your class to the autoptr. I know that for sure. I am not sure off the top of my head what syntax it wants but it should be something like p = new YourClass().
Related
How do I implement a copy constructor for a class that has a unique_ptr member variable? I am only considering C++11.
Since the unique_ptr can not be shared, you need to either deep-copy its content or convert the unique_ptr to a shared_ptr.
class A
{
std::unique_ptr< int > up_;
public:
A( int i ) : up_( new int( i ) ) {}
A( const A& a ) : up_( new int( *a.up_ ) ) {}
};
int main()
{
A a( 42 );
A b = a;
}
You can, as NPE mentioned, use a move-ctor instead of a copy-ctor but that would result in different semantics of your class. A move-ctor would need to make the member as moveable explicitly via std::move:
A( A&& a ) : up_( std::move( a.up_ ) ) {}
Having a complete set of the necessary operators also leads to
A& operator=( const A& a )
{
up_.reset( new int( *a.up_ ) );
return *this,
}
A& operator=( A&& a )
{
up_ = std::move( a.up_ );
return *this,
}
If you want to use your class in a std::vector, you basically have to decide if the vector shall be the unique owner of an object, in which case it would be sufficient to make the class moveable, but not copyable. If you leave out the copy-ctor and copy-assignment, the compiler will guide your way on how to use a std::vector with move-only types.
The usual case for one to have a unique_ptr in a class is to be able to use inheritance (otherwise a plain object would often do as well, see RAII). For this case, there is no appropriate answer in this thread up to now.
So, here is the starting point:
struct Base
{
//some stuff
};
struct Derived : public Base
{
//some stuff
};
struct Foo
{
std::unique_ptr<Base> ptr; //points to Derived or some other derived class
};
... and the goal is, as said, to make Foo copiable.
For this, one needs to do a deep copy of the contained pointer to ensure the derived class is copied correctly.
This can be accomplished by adding the following code:
struct Base
{
//some stuff
auto clone() const { return std::unique_ptr<Base>(clone_impl()); }
protected:
virtual Base* clone_impl() const = 0;
};
struct Derived : public Base
{
//some stuff
protected:
virtual Derived* clone_impl() const override { return new Derived(*this); };
};
struct Foo
{
std::unique_ptr<Base> ptr; //points to Derived or some other derived class
//rule of five
~Foo() = default;
Foo(Foo const& other) : ptr(other.ptr->clone()) {}
Foo(Foo && other) = default;
Foo& operator=(Foo const& other) { ptr = other.ptr->clone(); return *this; }
Foo& operator=(Foo && other) = default;
};
There are basically two things going on here:
The first is the addition of a user-defined copy constructor of Foo, This is necessary, as the unique_ptr-member iself has no copy constructor. In the declared copy-constructor, a new unique_ptr is created, and the pointer is set to a copy of the original pointee.
In case inheritance is involved, the copy of the original pointee must be done carefully. The reason is that doing a simple copy via std::unique_ptr<Base>(*ptr) in the code above would result in slicing, i.e., only the base component of the object gets copied, while the derived part is missing.
To avoid this, the copy has to be done via the clone-pattern. The
idea is to do the copy through a virtual function clone_impl()
which returns a Base* in the base class. In the derived class,
however, it is extended via covariance to return a Derived*, and
this pointer points to a newly created copy of the derived class. The
base class can then access this new object via the base class pointer
Base*, wrap it into a unique_ptr, and return it via the actual
clone() function which is called from the outside.
Second, by declaring a user-defined copy-constructor as done above, the move constructor gets deleted by the corresponding C++ language rules. The declaration via Foo(Foo &&) = default is thus just to let the compiler know that the standard move constructor still applies.
Try this helper to create deep copies, and cope when the source unique_ptr is null.
template< class T >
std::unique_ptr<T> copy_unique(const std::unique_ptr<T>& source)
{
return source ? std::make_unique<T>(*source) : nullptr;
}
Eg:
class My
{
My( const My& rhs )
: member( copy_unique(rhs.member) )
{
}
// ... other methods
private:
std::unique_ptr<SomeType> member;
};
Daniel Frey mention about copy solution,I would talk about how to move the unique_ptr
#include <memory>
class A
{
public:
A() : a_(new int(33)) {}
A(A &&data) : a_(std::move(data.a_))
{
}
A& operator=(A &&data)
{
a_ = std::move(data.a_);
return *this;
}
private:
std::unique_ptr<int> a_;
};
They are called move constructor and move assignment
you could use them like this
int main()
{
A a;
A b(std::move(a)); //this will call move constructor, transfer the resource of a to b
A c;
a = std::move(c); //this will call move assignment, transfer the resource of c to a
}
You need to wrap a and c by std::move because they have a name
std::move is telling the compiler to transform the value to
rvalue reference whatever the parameters are
In technical sense, std::move is analogy to something like "std::rvalue"
After moving, the resource of the unique_ptr is transfer to another unique_ptr
There are many topics that document rvalue reference; this is a pretty easy one to begin with.
Edit :
The moved object shall remain valid but unspecified state.
C++ primer 5, ch13 also give a very good explanation about how to "move" the object
I suggest use make_unique
class A
{
std::unique_ptr< int > up_;
public:
A( int i ) : up_(std::make_unique<int>(i)) {}
A( const A& a ) : up_(std::make_unique<int>(*a.up_)) {};
int main()
{
A a( 42 );
A b = a;
}
unique_ptr is not copyable, it is only moveable.
This will directly affect Test, which is, in your second, example also only moveable and not copyable.
In fact, it is good that you use unique_ptr which protects you from a big mistake.
For example, the main issue with your first code is that the pointer is never deleted which is really, really bad. Say, you would fix this by:
class Test
{
int* ptr; // writing this in one line is meh, not sure if even standard C++
Test() : ptr(new int(10)) {}
~Test() {delete ptr;}
};
int main()
{
Test o;
Test t = o;
}
This is also bad. What happens, if you copy Test? There will be two classes that have a pointer that points to the same address.
When one Test is destroyed, it will also destroy the pointer. When your second Test is destroyed, it will try to remove the memory behind the pointer, as well. But it has already been deleted and we will get some bad memory access runtime error (or undefined behavior if we are unlucky).
So, the right way is to either implement copy constructor and copy assignment operator, so that the behavior is clear and we can create a copy.
unique_ptr is way ahead of us here. It has the semantic meaning: "I am unique, so you cannot just copy me." So, it prevents us from the mistake of now implementing the operators at hand.
You can define copy constructor and copy assignment operator for special behavior and your code will work. But you are, rightfully so (!), forced to do that.
The moral of the story: always use unique_ptr in these kind of situations.
I have observed that the following code segfaults at the line ar.p():
#include <iostream>
class A
{
public:
virtual void p() { std::cout<<"A!\n"; }
};
class B : public A
{
public:
void p() { std::cout<<"B!\n"; }
};
struct Param
{
enum {AA, BB} tag;
union {
A a;
B b;
};
Param(const A &p)
: tag(AA) {a = p;}
A &get() {
switch(tag) {
case AA: return a;
case BB: return b;
}
}
};
int main() {
A a;
a.p();
Param u(a);
A &ar = u.get();
ar.p();
}
However, when I change the Param constructor to:
Param(const A &p)
: tag(AA), a(p) {}
it does not segfault anymore.
I think it has something to do with the way the vtable ptr for union member a is initialized, but I'd like to understand this bug better.
On coliru: http://coliru.stacked-crooked.com/a/85182239c9f033c1
The union doesn't have an implicit constructor, you have to add your own constructor to the union which initializes one of the members of the union. I think this is because the compiler can't know whether you want to initialize a or b. You may also need an assignment operator and destructor. See also this question: Why does union has deleted default constructor if one of its member doesn't have one whatsoever?
The constructor should use placement new or it can use a member initializer to construct one of the union members, as you do in your alternative constructor.
If you want to assign something to b afterwards, you have to destruct a using a.~A(), and then initialize b with placement new.
If you have members in the union with a non-trivial destructor then the union must have a destructor which calls the destructor on the member which is used at that point.
In your original code the assignment operator and the p() method are called without running a constructor first, leading to the crash.
How do I implement a copy constructor for a class that has a unique_ptr member variable? I am only considering C++11.
Since the unique_ptr can not be shared, you need to either deep-copy its content or convert the unique_ptr to a shared_ptr.
class A
{
std::unique_ptr< int > up_;
public:
A( int i ) : up_( new int( i ) ) {}
A( const A& a ) : up_( new int( *a.up_ ) ) {}
};
int main()
{
A a( 42 );
A b = a;
}
You can, as NPE mentioned, use a move-ctor instead of a copy-ctor but that would result in different semantics of your class. A move-ctor would need to make the member as moveable explicitly via std::move:
A( A&& a ) : up_( std::move( a.up_ ) ) {}
Having a complete set of the necessary operators also leads to
A& operator=( const A& a )
{
up_.reset( new int( *a.up_ ) );
return *this,
}
A& operator=( A&& a )
{
up_ = std::move( a.up_ );
return *this,
}
If you want to use your class in a std::vector, you basically have to decide if the vector shall be the unique owner of an object, in which case it would be sufficient to make the class moveable, but not copyable. If you leave out the copy-ctor and copy-assignment, the compiler will guide your way on how to use a std::vector with move-only types.
The usual case for one to have a unique_ptr in a class is to be able to use inheritance (otherwise a plain object would often do as well, see RAII). For this case, there is no appropriate answer in this thread up to now.
So, here is the starting point:
struct Base
{
//some stuff
};
struct Derived : public Base
{
//some stuff
};
struct Foo
{
std::unique_ptr<Base> ptr; //points to Derived or some other derived class
};
... and the goal is, as said, to make Foo copiable.
For this, one needs to do a deep copy of the contained pointer to ensure the derived class is copied correctly.
This can be accomplished by adding the following code:
struct Base
{
//some stuff
auto clone() const { return std::unique_ptr<Base>(clone_impl()); }
protected:
virtual Base* clone_impl() const = 0;
};
struct Derived : public Base
{
//some stuff
protected:
virtual Derived* clone_impl() const override { return new Derived(*this); };
};
struct Foo
{
std::unique_ptr<Base> ptr; //points to Derived or some other derived class
//rule of five
~Foo() = default;
Foo(Foo const& other) : ptr(other.ptr->clone()) {}
Foo(Foo && other) = default;
Foo& operator=(Foo const& other) { ptr = other.ptr->clone(); return *this; }
Foo& operator=(Foo && other) = default;
};
There are basically two things going on here:
The first is the addition of a user-defined copy constructor of Foo, This is necessary, as the unique_ptr-member iself has no copy constructor. In the declared copy-constructor, a new unique_ptr is created, and the pointer is set to a copy of the original pointee.
In case inheritance is involved, the copy of the original pointee must be done carefully. The reason is that doing a simple copy via std::unique_ptr<Base>(*ptr) in the code above would result in slicing, i.e., only the base component of the object gets copied, while the derived part is missing.
To avoid this, the copy has to be done via the clone-pattern. The
idea is to do the copy through a virtual function clone_impl()
which returns a Base* in the base class. In the derived class,
however, it is extended via covariance to return a Derived*, and
this pointer points to a newly created copy of the derived class. The
base class can then access this new object via the base class pointer
Base*, wrap it into a unique_ptr, and return it via the actual
clone() function which is called from the outside.
Second, by declaring a user-defined copy-constructor as done above, the move constructor gets deleted by the corresponding C++ language rules. The declaration via Foo(Foo &&) = default is thus just to let the compiler know that the standard move constructor still applies.
Try this helper to create deep copies, and cope when the source unique_ptr is null.
template< class T >
std::unique_ptr<T> copy_unique(const std::unique_ptr<T>& source)
{
return source ? std::make_unique<T>(*source) : nullptr;
}
Eg:
class My
{
My( const My& rhs )
: member( copy_unique(rhs.member) )
{
}
// ... other methods
private:
std::unique_ptr<SomeType> member;
};
Daniel Frey mention about copy solution,I would talk about how to move the unique_ptr
#include <memory>
class A
{
public:
A() : a_(new int(33)) {}
A(A &&data) : a_(std::move(data.a_))
{
}
A& operator=(A &&data)
{
a_ = std::move(data.a_);
return *this;
}
private:
std::unique_ptr<int> a_;
};
They are called move constructor and move assignment
you could use them like this
int main()
{
A a;
A b(std::move(a)); //this will call move constructor, transfer the resource of a to b
A c;
a = std::move(c); //this will call move assignment, transfer the resource of c to a
}
You need to wrap a and c by std::move because they have a name
std::move is telling the compiler to transform the value to
rvalue reference whatever the parameters are
In technical sense, std::move is analogy to something like "std::rvalue"
After moving, the resource of the unique_ptr is transfer to another unique_ptr
There are many topics that document rvalue reference; this is a pretty easy one to begin with.
Edit :
The moved object shall remain valid but unspecified state.
C++ primer 5, ch13 also give a very good explanation about how to "move" the object
I suggest use make_unique
class A
{
std::unique_ptr< int > up_;
public:
A( int i ) : up_(std::make_unique<int>(i)) {}
A( const A& a ) : up_(std::make_unique<int>(*a.up_)) {};
int main()
{
A a( 42 );
A b = a;
}
unique_ptr is not copyable, it is only moveable.
This will directly affect Test, which is, in your second, example also only moveable and not copyable.
In fact, it is good that you use unique_ptr which protects you from a big mistake.
For example, the main issue with your first code is that the pointer is never deleted which is really, really bad. Say, you would fix this by:
class Test
{
int* ptr; // writing this in one line is meh, not sure if even standard C++
Test() : ptr(new int(10)) {}
~Test() {delete ptr;}
};
int main()
{
Test o;
Test t = o;
}
This is also bad. What happens, if you copy Test? There will be two classes that have a pointer that points to the same address.
When one Test is destroyed, it will also destroy the pointer. When your second Test is destroyed, it will try to remove the memory behind the pointer, as well. But it has already been deleted and we will get some bad memory access runtime error (or undefined behavior if we are unlucky).
So, the right way is to either implement copy constructor and copy assignment operator, so that the behavior is clear and we can create a copy.
unique_ptr is way ahead of us here. It has the semantic meaning: "I am unique, so you cannot just copy me." So, it prevents us from the mistake of now implementing the operators at hand.
You can define copy constructor and copy assignment operator for special behavior and your code will work. But you are, rightfully so (!), forced to do that.
The moral of the story: always use unique_ptr in these kind of situations.
I mean, if i have some class like:
class A{
int* pi;
};
*A pa;
when i call delete pa, will pi be deleted?
You need to define a destructor to delete pi;. In addition you also need to define a copy constructor and assignment operator otherwise when an instance of A is copied two objects will be pointing to the same int, which will be deleted when one of the instances of A is destructed leaving the other instance of A with a dangling pointer.
For example:
class A
{
public:
// Constructor.
A(int a_value) : pi(new int(a_value)) {}
// Destructor.
~A() { delete pi; }
// Copy constructor.
A(const A& a_in): pi(new int(*a_in.pi)) {}
// Assignment operator.
A& operator=(const A& a_in)
{
if (this != &a_in)
{
*pi = *a_in.pi;
}
return *this;
}
private:
int* pi;
};
You should implement a destructor, ~A(), that takes care of cleaning up A's stuff. Afterwards, calling delete on a pointer of type A will clean-up everything.
You will need to write a destructor to delete all pointer type members. Something like:
class A
{
int *pi;
public:
~A(){delete pi;}
};
You will need to ensure that your constructor assigns a value to pi( at least a NULL). and like the answer from #hmjd, you will need to implement or hide the copy constructor and assignment operators. Look for the rule of three here:
http://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29
I have a C++ class hierarchy that looks something like this:
class A;
class B
{
public:
B( A& a ) : a_( a )
{
};
private:
A& a_;
};
class MyObject
{
public:
MyObject() : b_( a_ )
{
};
private:
A a_;
B b_;
};
Occasionally, it will happen that in B's destructor I will get invalid access exceptions relating to its reference of A. It appears that A is destroyed before B.
Is there something inherently wrong with using class members to initialize other members? Is there no guarantee of the order of destruction?
Thanks,
PaulH
EDIT: I missed the MyObject part of your question so my original answer will probably not be of much help. I guess your problem lies in the code you did not post, the stripped-down example should work fine.
Class B does not “own” the object passed by reference, therefore the objects a and b have different life cycles. If the object refered to by B::a_ is destroyed, B's destructor will access an invalid reference.
Some code to explain what I mean:
class A;
class B {
public:
B(A a) : a_(a) {} // a is copied to a_
~B() { /* Access a_ */ }
private:
A a_;
};
class C {
public:
C(A& a) : a_(a) {} // a_ is a reference (implicit pointer)
// of an external object.
~C() { /* Access a_ */ }
private:
A& a_;
};
int main(int argc, char** argv) {
A* a = new A();
B b(*a);
C c(*a);
delete a;
// Now b has a valid copy of a, c has an invalid reference.
}
In the code above the destruction order is well defined.
The destruction order is the reverse of the creation order.
The creation order is the order the members were declared within the class.
So in this case:
Default Construction:
a_: constructed first using default constructor.
b_: constructed using a valid a_ passed to the constructor.
Destruction:
b_: destroyed first. The destructor can use the reference to a
As long as the object has not been copied (see below)
a_: destroyed second.
But you have a potential problem if you make a copy of the object using the copy constructor.
The following copy constructor is defined by the compiler:
MyObject::MyObject(MyObject const& copy)
:a_(copy.a_)
,b_(copy.b_)
{}
So you may have a potential problem here. As the copy will contain an object 'b_' that contains a reference that was copied from another object. If the other object is destroyed then this 'b_' will have an invalid reference.
a_ should be constructed before b_, and b_ should be destructed before a_, based on the order you have defined them in MyObject.