Related
Sometimes I want to make classes/structs with const members. I realize that this is a bad idea for multiple reasons, but for the sake of argument let's pretend the only reason is that it makes a well-formed operator = a hassle, to say the least. However, I contrived a fairly simple work-around to it, as demonstrated by this struct:
struct S {
const int i;
S(int i) : i(i) {}
S(const S& other) : i(other.i) {}
S& operator =(const S& other) {
new (this) S(other);
return *this;
}
};
Ignoring destructors and move semantics, is there any really big reason why this shouldn't be done? It seems to me like a more type-safe version of
S& operator =(const S& other) {
const_cast<int&>(i) = other.i;
return *this;
}
So, the summary of the question is this: is there any major reason placement-new should not be used to implement copy assignment to have the same semantics as a copy construction?
I don't believe that placement new is a problem here but the const_cast which produces undefined behavior:
C++ 10.1.7.1-4
Except that any class member declared mutable (10.1.1) can be modified, any attempt to modify a const object during its lifetime (6.6.3) results in undefined behavior.
You'll probably get away with this until compiler starts to optimize things.
The other problem is the use of a placement new on a piece memory occupied by living (non-destroyed) object. But you'll probably get away with this while object in question has a trivial destructor.
is there any really big reason why this shouldn't be done?
You must be absolutely sure that every derived class defines its own assignment operator, even if it is trivial. Because an implicitly defined copy-assignment operator of a derived class will screw everything. It'll call S::operator= which will re-create a wrong type of object in its place.
Such destroy-and-construct assignment operator can't be re-used by any derived class. So, not only you are forcing derived classes to provide an explicit copy operator, but you're forcing them to stick to the same destroy-and-construct idiom in their assignment operator.
You must be absolutely sure that no other thread is accessing the object while it is being destroyed-and-constructed by such assignment operator.
A class may have some data members that must not be affected by the assignment operator. For example, a thread-safe class may have some kind of mutex or critical section member, with some other thread waiting on them right when the current thread is going to destroy-and-construct that mutex...
Performance-wise, it has virtually no advantage over standard copy-and-swap idiom. So what would be the gain in going through all the pain mentioned above?
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).
I recently revisited the copy constructor, assignment operator, copy swap idom seen here:
What is the copy-and-swap idiom?
and many other places -
The Above link is an excellent post - but I still had a few more questions -
These questions are answered in a bunch of places, on stackoverflow and many other sites, but I have not seen a lot of consistency -
1 - Should you have try-catch around the areas where we allocate the new memory for a deep copy in the copy constructor ? (Ive seen it both ways)
2 - With regards to inheritance for both the copy constructor and assignment operator, when should the base class functions be called, and when should these functions be virtual?
3 - Is std::copy the best way for duplicating memory in the copy constructor? I have seen it with memcpy, and seen others say memcpy the worst thing on earth.
Consider the example Below (Thanks for all the feedback), it prompted some additional questions:
4 - Should we be checking for self assignment? If so where
5 - Off topic question, but I have seen swapped used as :
std::copy(Other.Data,Other.Data + size,Data);
should it be:
std::copy(Other.Data,Other.Data + (size-1),Data);
if swap goes from 'First to Last' and the 0th element is Other.Data?
6 - Why doesn't the commented out constructor work (I had to change size to mysize) - is assume this means regardless of the order I write them, the constructor will always call the allocation element first?
7 - Any other comments on my implementation? I know the code is useless but i'm just trying to illustrate a point.
class TBar
{
public:
//Swap Function
void swap(TBar &One, TBar &Two)
{
std::swap(One.b,Two.b);
std::swap(One.a,Two.a);
}
int a;
int *b;
TBar& operator=(TBar Other)
{
swap(Other,*this);
return (*this);
}
TBar() : a(0), b(new int) {} //We Always Allocate the int
TBar(TBar const &Other) : a(Other.a), b(new int)
{
std::copy(Other.b,Other.b,b);
*b = 22; //Just to have something
}
virtual ~TBar() { delete b;}
};
class TSuperFoo : public TBar
{
public:
int* Data;
int size;
//Swap Function for copy swap
void swap (TSuperFoo &One, TSuperFoo &Two)
{
std::swap(static_cast<TBar&>(One),static_cast<TBar&>(Two));
std::swap(One.Data,Two.Data);
std::swap(One.size,Two.size);
}
//Default Constructor
TSuperFoo(int mysize = 5) : TBar(), size(mysize), Data(new int[mysize]) {}
//TSuperFoo(int mysize = 5) : TBar(), size(mysize), Data(new int[size]) {} *1
//Copy Constructor
TSuperFoo(TSuperFoo const &Other) : TBar(Other), size(Other.size), Data(new int[Other.size]) // I need [Other.size]! not sizw
{
std::copy(Other.Data,Other.Data + size,Data); // Should this be (size-1) if std::copy is First -> Last? *2
}
//Assignment Operator
TSuperFoo& operator=(TSuperFoo Other)
{
swap(Other,(*this));
return (*this);
}
~TSuperFoo() { delete[] Data;}
};
If you allocate memory then you need to ensure that it is freed in the case of an exception being thrown. You can do this with an explicit try/catch, or you can use a smart pointer such as std::unique_ptr to hold the memory, which will then be automatically deleted when the smart pointer is destroyed by stack unwinding.
You very rarely need a virtual assignment operator. Call the base class copy constructor in the member initialization list, and base-class assignment operator first in the derived assignment operator if you are doing a memberwise assignment --- if you are doing copy/swap then you don't need to call the base class assignment in your derived assignment operator, provided that copy and swap are implemented correctly.
std::copy works with objects, and will correctly call copy constructors. If you have plain POD objects then memcpy will work just as well. I'd go for std::copy in most cases though --- it should be optimized to memcpy under the hood anyway for PODs, and it avoids the potential for errors should you add a copy constructor later.
[Updates for updated question]
With copy/swap as written there is no need to check for self-assignment, and indeed no way of doing so --- by the time you enter the assignment operator other is a copy, and you have no way of knowing what the source object was. This just means that self-assignment will still do a copy/swap.
std::copy takes a pair of iterators (first, first+size) as input. This allows for empty ranges, and is the same as every range-based algorithm in the standard library.
The commented out constructor doesn't work because the members are initialized in the order they are declared, regardless of the order in the member initializer list. Consequently, Data is always initialized first. If the initialization depends on size then it will get a duff value since size hasn't been initialized yet. If you swap the declarations of size and data then this constructor will work fine. Good compilers will warn about the order of member initialization not matching the order of declarations.
1 - Should you have try-catch around the areas where we allocate the new memory for a deep copy in the copy constructor ?
In general, you should only catch an exception if you can handle it. If you have a way of dealing with an out-of-memory condition locally, then catch it; otherwise, let it go.
You should certainly not return normally from a constructor if construction has failed - that would leave the caller with an invalid object, and no way to know that it's invalid.
2 - With regards to inheritance for both the copy constructor and assignment operator, when should the base class functions be called, and when should these functions be virtual?
A constructor can't be virtual, since virtual functions can only be dispatched by an object, and there is no object before you create it. Usually, you wouldn't make assignment operators virtual either; copyable and assignable classes are usually treated as non-polymorphic "value" types.
Usually, you'd call the base class copy constructor from the initialiser list:
Derived(Derived const & other) : Base(other), <derived members> {}
and if you're using the copy-and-swap idiom, then your assignment operator wouldn't need to worry about the base class; that would be handled by the swap:
void swap(Derived & a, Derived & b) {
using namespace std;
swap(static_cast<Base&>(a), static_cast<Base&>(b));
// and swap the derived class members too
}
Derived & Derived::operator=(Derived other) {
swap(*this, other);
return *this;
}
3 - Is std::copy the best way for duplicating memory in the copy constructor? I have seen it with memcopy, and seen others say memcopy the worst thing on earth.
It's rather unusual to be dealing with raw memory; usually your class contains objects, and often objects can't be correctly copied by simply copying their memory. You copy objects using their copy constructors or assignment operators, and std::copy will use the assignment operator to copy an array of objects (or, more generally, a sequence of objects).
If you really want, you could use memcpy to copy POD (plain old data) objects and arrays; but std::copy is less error-prone (since you don't need to provide the object size), less fragile (since it won't break if you change the objects to be non-POD) and potentially faster (since the object size and alignment are known at compile time).
If the constructor for what you're deep copying may throw something
you can handle, go ahead and catch it. I'd just let memory
allocation exceptions propagate, though.
Copy constructors (or any constructors) can't be virtual. Include a
base class initializer for these. Copy assignment operators should
delegate to the base class even if they're virtual.
memcpy() is too low-level for copying class types in C++ and can lead to undefined behavior. I think std::copy is usually a better choice.
try-catch can be used when you have to undo something. Otherwise, just let the bad_alloc propagate to the caller.
Calling the base class' copy constructor or assignment operator is the standard way of letting is handle its copying. I have never seen a use case for a virtual assignment operator, so I guess they are rare.
std::copy has the advantage that it copies class objects correctly. memcpy is rather limited on what types it can handle.
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).
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.