Creating an easy to maintain copy constructor - c++

Consider the following class:
class A {
char *p;
int a, b, c, d;
public:
A(const &A);
};
Note that I have to define a copy constructor in order to do a deep copy of "p". This has two issues:
Most of the fields should simply be copied. Copying them one by one is ugly and error prone.
More importantly, whenever a new attribute is added to the class, the copy constructor needs to be updated, which creates a maintenance nightmare.
I would personally like to do something like:
A(const A &a) : A(a)
{
// do deep copy of p
:::
}
So the default copy constructor is called first and then the deep copy is performed.
Unfortunately this doesn't seem to work.
Is there any better way to do this?
One restriction - I can't use shared/smart pointers.
Sbi's suggestions make a lot of sense. I think I'll go with creating wrapper classes for handling the resource. I don't want to user shared_ptr since boost libraries may not be available on all platforms (at least not in standard distributions, OpenSolaris is an example).
I still think it would have been great if you could somehow make the compiler to create the default constructor/assignment operators for you and you could just add your functionality on top of it. The manually created copy constructor/assignment operator functions I think will be a hassle to create and a nightmare to maintain. So my personal rule of thumb would be to avoid custom copy constructors/assignment operators at all cost.
Thanks everybody for their responses and helpful information and sorry about typos in my question. I was typing it from my phone.

As a rule of thumb: If you have to manually manage resources, wrap each into its own object.
Put that char* into its own object with a proper copy constructor and let the compiler do the copy constructor for A. Note that this also deals with assignment and destruction, which you haven't mentioned in your question, but need to be dealt with nevertheless.
The standard library has several types to pick from for that, among them std::string and std::vector<char>.

Replace char* with std::string.

Always use RAII objects to manage unmanages resources such as raw pointers, and use exactly one RAII object for each resource. Avoid raw pointers in general. In this case, using std::string is the best solution.
If that's not possible for some reason, factor the easy to copy parts out into a base class or a member object.

You could separate your copyable members into a POD-struct and mantain your members requiring a managed copy separately.
As your data members are private this can be invisible to clients of your class.
E.g.
class A {
char *p;
struct POData {
int a, b, c, d;
// other copyable members
} data;
public:
A(const &A);
};
A(const A& a)
: data( a.data )
{
p = DuplicateString( a.p );
// other managed copies...
// careful exception safe implementation, etc.
}

You really should use smart pointers here.
This would avoid rewriting both the copy constructor and the affectation operator (operator=).
Both of these are error prone.
A common mistake with the operator= is implementing it that way:
SomeClass& operator=(const SomeClass& b)
{
delete this->pointer;
this->pointer = new char(*b.pointer); // What if &b == this or if new throws ?
return *this;
}
Which fails when one does:
SomeClass a;
a = a; // This will crash :)
Smart pointers already handle those cases and are obviously less error prone.
Moreover, Smart pointers, like boost::shared_ptr can even handle a custom deallocation function (by default it uses delete). In practice, I rarely faced a situation where using a smart pointer instead of a raw pointer was unpractical.
Just a quick note: boost smart pointer class, are header-only designed (based on templates) so they don't require additional dependencies. (Sometimes, it matters) You can just include them and everything should be fine.

The question is, do you really need a pointer with deep-copy semantics in your class? In my experience, the answer almost always is no. Maybe you could explain your scenario, so we may show you alternative solutions.
That said, this article describes an implementation of a smart-pointer with deep-copy semantics.

While I agree with others saying that you should wrap the pointer in its own class for RAII and let the compiler synthesise the copy contructor, destructor and assignment operator there is a way around your problem: declare (and define) private static function which will do whatever is needed and common for different constructors and call it from there.

Unless your class has one function, which is managing a resource, you should never manage any resources directly. Always use a smart pointer or custom management class of some description. Typically, it's best to leave the implicit copy constructor, if you can. This approach also allows easy maintenance of the destructor and assignment operators.

So the default copy constructor is called first and then the deep copy is performed.
Unfortunately this doesn't seem to work.
Is there any better way to do this? One restriction - I can't use shared/smart pointers.
If I understand correctly, your question, you could consider using an initialization function:
class A
{
int i, j;
char* p;
void Copy(int ii, int jj, char* pp); // assign the values to memebers of A
public:
A(int i, int j, char* p);
A(const A& a);
};
A::A(int i, int j, char* p)
{
Copy(i, j, p);
}
A::A(const A& a)
{
Copy(a.i, a.j, a.p);
}
That said, you really should consider using RAII ( there's a reason people keep recommending it :) ) for your extra resources.
If I can't use RAII, I still prefer creating the copy constructor and using initializer lists, for every member (actually, I prefer doing so even when using RAII):
A::A(int ii, int lj, char* pp)
: i(ii)
, j(jj)
, p( function_that_creates_deep_copy(pp) )
{
}
A::A(const A& a)
: i(a.i)
, j(a.j)
, p( function_that_creates_deep_copy(a.p) )
{
}
This has the advantage of "explicitness" and is easy to debug (you can step in and see what it does for each initialization).

Related

Unique Pointers and The Rule of 3

I often find myself using unique pointers in C++ when I want polymorphic behaviour. I typically implement pure abstract classes something like the below:
class A {
public:
virtual A* clone() const = 0; // returns a pointer to a deep copy of A
// other methods go here
};
The clone method comes in handy when I want to embellish another class with its own instance of A, for example:
#include <memory>
class B {
private:
std::unique_ptr<A> a_ptr;
public:
// ctor
B(const A& a) {
a_ptr = std::unique_ptr<A>(a.clone());
//...
}
// copy ctor
B(const B& other) : B(*other.a_ptr) {}
};
I invariably end up implementing the copy constructor in B to avoid a compiler error (MSVC gives a vague message about attempting to reference a deleted function), which makes complete sense because of the unique pointer. My questions can be summarised as follows:
Do I actually need the copy constructor in B? Perhaps there's a better pattern that would allow me to avoid it altogether.
If yes to 1, can I stop there? Will I ever need to implement the other default functions? I.e. is there any scenario where I need a default constructor and destructor also?
In practice, whenever I feel I need to implement the default functions, I typically implement a move-constructor alongside the other three; I usually use the copy-and-swap-idiom (as per GManNickG's answer in this thread). I assume this wouldn't change anything, but maybe I am wrong!
Thanks a lot!
First, I think the signature of your clone function could be
virtual std::unique_ptr<A> clone() = 0;
as you want deep copies of A instances and exclusive ownership within B. Second, you indeed have to define a copy constructor for your class when you want it to be copyable. Same for an assignment operator. This is due to the fact that std::unique_ptr is a move-only type, which hinders the compiler to generate default implementations.
Other special member functions are not needed, though they might make sense. The compiler won't generate move constructor and move assignment operator for you (as you ship your own copy/assignment functions), though in your case, you can = default; them easily. The destructor can equally well be defined with = default;, which would be in line with the core guidelines.
Note that defining the destructor via = default should be done in a translation unit, as std::unique_ptr requires the full type do be known upon freeing its resource.
Whether you need a default constructor totally depends on how yo want to use the class B.
As #lubgr mentioned in his answer, You should return unique_ptr not a raw one from the clone function. Anyway, going to Your questions:
Do You need a copy constructor in B? Well it depends on Your use cases, but if You copy objects of class B You may need one. But as You said, You do it quite often, so it would be wise to consider more generic approach. One of these would be creating a wrapper for unique_ptr which would have copy constructor and which would make a deep copy of this pointer in this copy constructor.
Consider following example:
template<class T>
class unique_ptr_wrap {
public:
unique_ptr_wrap(std::unique_ptr< T > _ptr) : m_ptr(std::move(_ptr)){}
unique_ptr_wrap(const unique_ptr_wrap &_wrap){
m_ptr = _wrap->clone();
}
unique_ptr_wrap(unique_ptr_wrap &&_wrap){
m_ptr = std::move(_wrap.m_ptr);
}
T *operator->() const {
return m_ptr.get();
}
T &operator*() const {
return *m_ptr;
}
private:
std::unique_ptr< T > m_ptr;
};
This again depends on Your needs. I personally would recommend overloading move constructor as well, to make it use less dynamic allocations (but this may be premateure optimization which is root of all evil).

Array class member initialization in C++

I have the following code snippet:
#include <iostream>
using namespace std;
class A {
int* data;
int size;
public:
A(int s):size(s)
{
data = new int[size];
}
A() {
data = nullptr;
}
~A() {
if (data) delete [] data;
}
};
class B {
A a[2];
public:
B() {
a[0] = A(10);
a[1] = A(11);
}
};
int main(int argc, char *argv[]) {
B b;
}
In the C++ code above, I have class A which has an array member int* data, and the (de)allocation of memory are handled by (de)constructor. The I created class B which has an array of class A of fixed length as a data member.
My question is: how to elegantly initialise the member A a[2]? In the code above, the A(10) and A(11) are created on the stack, when jumping out of the scope, their destructors will be called, hence the data comes invalid. When jumping of the main function's scope, the pointers held by a[2] will be deallocated twice, causing the error:
pointer being freed was not allocated.
One possible solution is to carefully design a copy constructor and a move constructor, by doing so the above coding paradigm could work.
Another solution I've tried is to initialise the array in the initialization list of class B:
B() : a { A(10), A(11) }
This solution works and I don't really tell the underlying mechanism of initialization list. I think it must be quite different from simply construct and copy. I really expected some experts could give an elaborate explanation of this mechanism. Of course, this solution is ugly hard-coded and not flexible.
So I wonder if there are some programming paradigms in C++ to tackle this design problem?
In the code above, the A(10) and A(11) are created on the stack
They are temporary objects. It is not specified where they are created or if they're created at all.
when jumping out of the scope, their destructors will be called
The destructor of each temporary will be called after the corresponding move assignment statement ends.
One possible solution is to carefully design a copy constructor and a move constructor, by doing so the above coding paradigm could work.
And {copy,move} assignment operator too. You should always do that when the implicitly declared ones don't do the right thing. And they never do the right thing if you delete something in the destructor.
Another solution I've tried is to initialise the array in the initialization list of class B
This solution works and I don't really tell the underlying mechanism of initialization list. I think it must be quite different from simply construct and copy.
The bug in the original code is badly behaving move assignment operator of A. Since the initialization list never move assigns from a temporary, it never triggers the bug.
This is actually the more elegant way to construct a that you asked for. Not because it avoids the bug, but because avoiding unnecessary moving is good thing, intrinsically.
So I wonder if there are some programming paradigms in C++ to tackle this design problem?
Yes. RAII and Single responsibility principle. Unless your class does nothing else, besides managing the memory pointed by data, it should not be managing the memory. Instead, it should delegate the memory management to a RAII object. In this case, you should use a std::vector member.
class A {
std::vector<int> data;
public:
A(int s):data(s) {}
A() = default;
};
Using an initializer list to construct B::a, like this:
class B {
A a[2];
public:
B() : a({10, 11}){
}
};
The ideal answer would be to force A to use movements instead of copies, or on a copy to allocate new space for the item. Of the two, the most efficient is the former and so I will expand on it below:
Forcing movement can be done in two fashions:
Delete the copy constructor and copy operator=, and implement your own move constructor and operator=
Consistently use std::move and std::swap.
Of these, the former is superior in that you will be unable to accidentally copy the class, but with the latter the fact that you are moving will be more evident.
To delete the default copy methods do:
class A {
A( const A& a ) = delete;
A& operator =( const A& a ) = delete;
}

Using '=' for Classes without Defining '=' Operator in C++

Is the following assignment valid?
class A {
int a;
public:
A(int k): a(k){}
}
void main() {
A first (5);
A second;
second = first;
}
If it is valid, what happens for second? Does C++ makes a deep copy? Or a shallow copy?
Perhaps you are new to C++, perhaps a student?
You are lucky, since the data member for your A class is an integer. Which is a plain old data type. Called POD for short. BTW: You tagged your question with copy-constructor, but demonstrated in your example an assignment operator.
They are two different things.
A copy constructor makes a new instance based off of another instance. Like this:
class A
{
public:
A(A& other) { ... }
};
An assignment operator looks like this:
class A
{
public:
const A& operator=(const A& other) { ... }
};
Since you did not provide your own assignment operator, the compiler made one for you. In fact the compiler will also make a destructor for you too. Isn't that nice? Well don't always trust your compiler. If your classes have anything beyond Plain old Data, then please get in the habit of providing your own constructors, destructors, assignment operators. It's a rule I live by. I'd hate to have a bug that takes 2 days to track down to say... a memory leak due to my forgetting to deallocate memory in a destructor.
In your case, the compiler made a shallow copy for you. A compiler will never make a deep copy for you. You have to do that yourself.
Since you wrote one form of constructor, compiler will not provide default constructor so your declaration 'A second;' will not compile. You could possibly do A second(0); and then second = first;

Is it bad form to call the default assignment operator from the copy constructor?

Consider a class of which copies need to be made. The vast majority of the data elements in the copy must strictly reflect the original, however there are select few elements whose state is not to be preserved and need to be reinitialized.
Is it bad form to call a default assignment operator from the copy constructor?
The default assignment operator will behave well with Plain Old Data( int,double,char,short) as well user defined classes per their assignment operators. Pointers would need to be treated separately.
One drawback is that this method renders the assignment operator crippled since the extra reinitialization is not performed. It is also not possible to disable the use of the assignment operator thus opening up the option of the user to create a broken class by using the incomplete default assignment operator A obj1,obj2; obj2=obj1; /* Could result is an incorrectly initialized obj2 */ .
It would be good to relax the requirement that to a(orig.a),b(orig.b)... in addition to a(0),b(0) ... must be written. Needing to write all of the initialization twice creates two places for errors and if new variables (say double x,y,z) were to be added to the class, initialization code would need to correctly added in at least 2 places instead of 1.
Is there a better way?
Is there be a better way in C++0x?
class A {
public:
A(): a(0),b(0),c(0),d(0)
A(const A & orig){
*this = orig; /* <----- is this "bad"? */
c = int();
}
public:
int a,b,c,d;
};
A X;
X.a = 123;
X.b = 456;
X.c = 789;
X.d = 987;
A Y(X);
printf("X: %d %d %d %d\n",X.a,X.b,X.c,X.d);
printf("Y: %d %d %d %d\n",Y.a,Y.b,Y.c,Y.d);
Output:
X: 123 456 789 987
Y: 123 456 0 987
Alternative Copy Constructor:
A(const A & orig):a(orig.a),b(orig.b),c(0),d(orig.d){} /* <-- is this "better"? */
As brone points out, you're better off implementing assignment in terms of copy construction. I prefer an alternative idiom to his:
T& T::operator=(T t) {
swap(*this, t);
return *this;
}
It's a bit shorter, and can take advantage of some esoteric language features to improve performance. Like any good piece of C++ code, it also has some subtleties to watch for.
First, the t parameter is intentionally passed by value, so that the copy constructor will be called (most of the time) and we can modify is to our heart's content without affecting the original value. Using const T& would fail to compile, and T& would trigger some surprising behaviour by modifying the assigned-from value.
This technique also requires swap to be specialized for the type in a way that doesn't use the type's assignment operator (as std::swap does), or it will cause an infinite recursion. Be careful of any stray using std::swap or using namespace std, as they will pull std::swap into scope and cause problems if you didn't specialize swap for T. Overload resolution and ADL will ensure the correct version of swap is used if you have defined it.
There are a couple of ways to define swap for a type. The first method uses a swap member function to do the actual work and has a swap specialization that delegates to it, like so:
class T {
public:
// ....
void swap(T&) { ... }
};
void swap(T& a, T& b) { a.swap(b); }
This is pretty common in the standard library; std::vector, for example, has swapping implemented this way. If you have a swap member function you can just call it directly from the assignment operator and avoid any issues with function lookup.
Another way is to declare swap as a friend function and have it do all of the work:
class T {
// ....
friend void swap(T& a, T& b);
};
void swap(T& a, T& b) { ... }
I prefer the second one, as swap() usually isn't an integral part of the class' interface; it seems more appropriate as a free function. It's a matter of taste, however.
Having an optimized swap for a type is a common method of achieving some of the benefits of rvalue references in C++0x, so it's a good idea in general if the class can take advantage of it and you really need the performance.
With your version of the copy constructor the members are first default-constructed and then assigned.
With integral types this doesn't matter, but if you had non-trivial members like std::strings this is unneccessary overhead.
Thus, yes, in general your alternative copy constructor is better, but if you only have integral types as members it doesn't really matter.
Essentially, what you are saying is that you have some members of your class which don't contribute to the identity of the class. As it currently stands you have this expressed by using the assignment operator to copy class members and then resetting those members which shouldn't be copied. This leaves you with an assignment operator that is inconsistent with the copy constructor.
Much better would be to use the copy and swap idiom, and express which members shouldn't be copied in the copy constructor. You still have one place where the "don't copy this member" behaviour is expressed, but now your assignment operator and copy constructor are consistent.
class A
{
public:
A() : a(), b(), c(), d() {}
A(const A& other)
: a(other.a)
, b(other.b)
, c() // c isn't copied!
, d(other.d)
A& operator=(const A& other)
{
A tmp(other); // doesn't copy other.c
swap(tmp);
return *this;
}
void Swap(A& other)
{
using std::swap;
swap(a, other.a);
swap(b, other.b);
swap(c, other.c); // see note
swap(d, other.d);
}
private:
// ...
};
Note: in the swap member function, I have swapped the c member. For the purposes of use in the assignment operator this preserves the behaviour to match that of the copy constructor: it re-initializes the c member. If you leave the swap function public, or provide access to it through a swap free function you should make sure that this behaviour is suitable for other uses of swap.
Personally I think the broken assignment operator is killer. I always say that people should read the documentation and not do anything it tells them not to, but even so it's just too easy to write an assignment without thinking about it, or use a template which requires the type to be assignable. There's a reason for the noncopyable idiom: if operator= isn't going to work, it's just too dangerous to leave it accessible.
If I remember rightly, C++0x will let you do this:
private:
A &operator=(const A &) = default;
Then at least it's only the class itself which can use the broken default assignment operator, and you'd hope that in this restricted context it's easier to be careful.
I would call it bad form, not because you double-assign all your objects, but because in my experience it's often bad form to rely on the default copy constructor / assignment operator for a specific set of functionality. Since these are not in the source anywhere, it's hard to tell that the behavior you want depends on their behavior. For instance, what if someone in a year wants to add a vector of strings to your class? You no longer have the plain old datatypes, and it would be very hard for a maintainer to know that they were breaking things.
I think that, nice as DRY is, creating subtle un-specified requirements is much worse from a maintenance point of view. Even repeating yourself, as bad as that is, is less evil.
I think the better way is not to implement a copy constructor if the behaviour is trivial (in your case it appears to be broken: at least assignment and copying should have similar semantics but your code suggests this won't be so - but then I suppose it is a contrived example). Code that is generated for you cannot be wrong.
If you need to implement those methods, most likely the class could do with a fast swap method and thus be able to reuse the copy constructor to implement the assignment operator.
If you for some reason need to provide a default shallow copy constructor, then C++0X has
X(const X&) = default;
But I don't think there is an idiom for weird semantics. In this case using assignment instead of initialization is cheap (since leaving ints uninitialized doesn't cost anything), so you might just as well do it like this.

How do use a std::auto_ptr in a class you have to copy construct?

I have class foo that contains a std::auto_ptr member that I would like to copy construct but this does not appear to be allowed. There's a similar thing for the assignment. See the following example:
struct foo
{
private:
int _a;
std::string _b;
std::auto_ptr< bar > _c;
public:
foo(const foo& rhs)
: _a(rhs._a)
, _b(rhs._b)
, _c(rhs._c)
// error: Cannot mutate rhs._c to give up ownership - D'Oh!
{
}
foo& operator=(const foo& rhs)
{
_a = rhs._a;
_b = rhs._b;
_c = rhs._c;
// error: Same problem again.
}
};
I could just declare _c as mutable but I'm not sure this is correct. Does anyone have a better solution?
EDIT
OK, I'm not getting the kind of answer that I was expecting so I'll be a little more specific about the problem.
An object of type foo is created on the stack and passed by value into a container class (not stl) and then goes out of scope. I don't have any control over the container code. (It's actually an active queue implementation, with bugs.)
The bar class is a fairly heavyweight parser. It has very poor performance on new and delete so even if it was copy constructable, it would be way too expensive.
We can guarantee that when a bar object is created, it will only ever need to be owned in 1 place at a time. In this case it is being passed between threads and deleted when the transaction is completed. This is why I was hoping to use a std::autp_ptr.
I am very willing to consider boost smart pointers but I was hoping to guarantee this uniqueness if there is an alternative.
You might want to try following code:
foo(const foo& rhs)
: _a(rhs._a)
, _b(rhs._b)
, _c(_rhs._c.get() ? new bar(*_rhs._c.get()) : 0)
{
}
(Assignment operator is similar.)
However this will only work if bar is CopyConstructible and if this indeed does what you want. The thing is that both foo objects (_rhs and constructed one) will have different pointers in _c.
If you want them to share the pointer then you must not use auto_ptr as it does not support shared ownership. Consider in such case use of shared_ptr from Boost.SmartPtr for example (which will be included in new C++ standard). Or any other shared pointer implementation as this is such a common concept that lots of implementations are available.
As you have discovered you can't copy a std::auto_ptr like that. After the copy who owns the object pointed to? Instead you should use a reference counted smart pointer. The Boost library has a shared_ptr you could use.
First, I'd avoid auto_ptr
Transfer of ownership is good in some scenarios, but I find they are rare, and "full fledged" smart pointer libraries are now available easily. (IIRC auto_ptr was a compromise to include at least one example in the standard library, without the delays that a good implementation would have required).
See, for example here
or here
Decide on semantics
Should the copy of foo hold a reference to the same instance of bar? In that case, use boost::shared_ptr or (boost::intrusive_ptr), or a similar library.
Or should a deep copy be created?
(That may sometimes be required, e.g. when having delay-created state). I don't know any standard implementation of that concept, but it's not to complex to build that similar to existing smart pointers.
// roughly, incomplete, probably broken:
template <typename T>
class deep_copy_ptr
{
T * p;
public:
deep_copy_ptr() : p(0) {}
deep_copy_ptr(T * p_) : p(p_) {}
deep_copy_ptr(deep_copy_ptr<T> const & rhs)
{
p = rhs.p ? new T(*rhs.p) : 0;
}
deep_copy_ptr<T> & operator=(deep_copy_ptr<T> const & rhs)
{
if (p != rhs.p)
{
deep_copy_ptr<T> copy(rhs);
swap(copy);
}
}
// ...
}
The std::auto_ptr is a good tool for managing dynamic object in C++ but in order to use it effectivelly it's important to unserstand how auto_ptr works. This article explains why, when and where this smart pointer should be used.
In your case, first of all your should decide what you want to do with the object inside your auto_ptr. Should it be cloned or shared?
If it should be cloned, make sure it has a copy constructor and then your create a new auto_ptr which contains a copy of your the object see Adam Badura's answer.
If it should shared, you should use boost::shared_ptr as Martin Liversage suggested.
If I have class containing an auto_ptr, and want deep-copy semantics, I generatally only do this for classes that have a virtual copy operator, i.e. clone().
Then, within the copy constructor, I initialize the auto_ptr to a clone() of the other; e.g.
class Foo
{
public:
Foo(const Foo& rhs) : m_ptr(rhs.m_ptr->clone());
private:
std::auto_ptr<T> m_ptr;
};
clone() is typically implemented as follows:
class T
{
std::auto_ptr<T> clone() const
{
return std::auto_ptr<T>(new T(*this));
}
};
We are imposing the condition that T is clonable, but this condition is essentially imposed by having a copiable class with an auto_ptr member.
The whole idea of the auto_ptr is that there's only one owner of the referred to object. This implies you cannot copy the pointer without removing the original ownership.
Since you cannot copy it, you also can't copy an object containing an auto_ptr.
You might try to use move-semantics by e.g. using std::swap instead of copy.
My first choice would be to avoid auto_ptr in this situation altogether. But if I were backed against a wall, I might try to use the keyword mutable in the declaration of _c - this will allow it to be modified even from a const reference.
Given the edit, then it appears you want tranfer of ownership semantics.
In that case, then you'll want to have your copy constructor and assignment operator accept non-const references to their arguments, and perform the initialization/assignment there.
You can't use const references in a copy constructor or assignment operator that involves an auto_ptr<>. Remove the const. In other words, use declarations like
foo(foo & rhs);
foo & operator=(foo & rhs);
These forms are explicitly mentioned in the Standard, primarily in section 12.8. They should be usable in any standard-conforming implementation. In fact, paragraphs 5 and 10 of 12.8 says that the implicitly defined copy constructor and assignment operator (respectively) will take a non-const reference if any of the members require it.