Do we only need to write a copy constructor and assignment operator when we have pointer data members (because otherwise two pointers could point to the same object when the compiler-generated copy ctor does a shallow copy)?
If all our data members are allocated on the stack we can just rely on compiler-defined copy constructor and assignment operator?
Pointers are undoubtedly the most obvious case, but not really the only one.
Another example would be a class that opens a database connection in the ctor and closes it in the dtor. A copy ctor would need to do something to duplicate the database connection, so the copy's connection to the database is closed separately from the original's connection.
Use the compiler defined copy constructor if it works.
The shallow copy is typically faster, and even though they may cope the pointer address instead of the pointed data that can be what you want in some cases. For example you might want a pointer to the texture that you share with other parts of the code.
Only if you need a copy of the data you should fix the copy constructor.
A warning would be member variables that are classes with their own copy constructors, can't give you any promises on what happens then.
If a base class or an object contained by the class has no copy constructor (ie. a stream) then if you wish your class to be copy constructable then you must implement a copy constructor.
For the stream case, this copy constructor may have to
a) duplicate the file,
b) create a new empty file that can be written to,
c) or save the address of the stream so that both objects can write to it.
The last option is the most complicated and would probably require use of a shared_ptr.
Generally, I like to put all my resources into classes maintaining these resources and these tesource maintainer need a copy construct, copy assignment, and a destructor. Depending on the resource, the copy constructor and copy assignment may be deleted.
What is not as obvious is that some classes not maintaining resources directly may need a copy assignment: if you want your copy assignment to be strongly exception safe, you often need to implement the copy assignment. For example, assume your class stores two vectors. The generated copy assgnment does a memberwise assignment. Normally, memberwise assignment is fine. However, if the assgnment to the second vector throws an exception, it is impossible to restore the original state! A better copy assgnment would look like that:
T& T::operator= (T other) {
other. swap(*this);
return *this;
}
Since swap() can be implemented without throwing, This imolementation is strongly exception-safe.
Related
Why C++ provide a copy constructor? The assignment operator can do the same task. Is there any advantage of copy constructor over assignment operator?
Stuff you can do with a copy constructor that you can't do (either easily or at all) with the assignment operator:
Copy classes that don't have a default constructor. For example, if a class represents an open file, you might not be able to construct one without passing it a file name to open.
Copy classes that have an expensive default constructor. Maybe the constructor allocates a lot of memory, which will then be released as soon as you use the assignment operator to copy a new state into the object.
Pass an instance of the class by value. This is kind of the original purpose of the copy constructor. In C, if you pass a struct by value, the compiler just does a bitwise copy of the struct so the receiving function has a local copy that it can modify without affecting the caller. But C++ recognizes that a bitwise copy is not the best way to copy most objects, so it lets you write your own copy constructor (and the default copy behavior is different too, since class members may have custom copy constructors).
Copy a class that contains references, because you can't reassign a reference after the class has already been constructed. The copy constructor and assignment operator just do different things where references are concerned. The copy constructor initializes the reference to point to the same object that the reference points to in the instance that is being copied; the assignment operator actually copies the value of the referenced object.
Copy a class with const members. (Note that a class can have a default constructor but still have const members.)
With or without a copy constructor, you still have to initialize a new object to a stable initial state, which the assignment operator can then update later.
While you can certainly do that without a copy constructor, having a copy constructor helps to optimize a new object's initialization, by setting it to copy another object's state up front, without requiring you to first initialize the new object to a default state and then have a separate assignment reset that state afterwards. This way, you can set the new object's state in 1 operation instead of 2 operations.
Yes, the two are different. You can't always just implement your copy constructor as
Foo(const Foo& f) {
*this = f;
}
The assignment operator assumes that you have a valid, fully constructed object. The copy constructor makes no such assumptions. This means that, depending on your class, the assignment operator may try to clear whatever data is on the object before re-initializing. Or may even repurpose the data already on the object.
Take this example.
Jack and John are twins.
You could say this is Jack and that is Jack.
But although John is the spitting image of Jack, he ain't no Jack.
When you use the assignment operator you can refer to the exact object in memory (returning *this) or provide some custom behavior.
When you use the copy constructor you want to create another object in memory that has a copy of the properties of the original object, but that can evolve in a different direction.
If you want a deeper answer I think this blog post is better.
Assignment is a little more tricky than initialization, because what
we are essentially doing is destructing the existing object and then
re-constructing it with new values. In a more complex class, you might
need to free various resources and then re-allocate them using copies
of the resources from the object being copied. std::unique_ptr makes
our life easy here, because assigning a new instance of
std::unique_ptr to an existing std::unique_ptr object with = as above
(or by using reset()) first frees the old pointer, so releasing the
resource is handled for us automatically (this is the same reason our
class doesn’t need a destructor – when std::unique_ptr goes out of
scope as our object goes out of scope, std::unique_ptr‘s destructor is
called and the resource is freed automatically).
I read two articles on stackOverflow,one describing the copy and swap idiom and the other talking about move semantics,but I fail to see why we need to swap in the assignment operator when the move constructor or copy constructor has already done that for us
so from what I understand as explained if we use an lvalue the assignment operator will construct an object with the copy constructor if an rvalue it will construct an object with the move constructor,so lets say we choose the latter
lets say we have a function that swaps objects members and below is the assignment operator,so as I said lets say we have an rvalue first the operator= will construct an object with the move constructor so why so we need the swap function here??
we have already accomplished what we want we have made an object with the move constructor and "stolen or taken" the data we needed so whats the need for the extra swap?
aren't we just doing the same thing all over again just swapping?
here are the articles/threads
What are move semantics?
What is the copy-and-swap idiom?
dumb_array& operator=(dumb_array other) // (1)
{
swap(*this, other); // (2)
return *this;
}
There are two concerns when assigning an object:
We want to get a copy of source's contents into destination.
We want the original contents of destination to be correctly disposed of.
Since we have a copy constructor, the first step is done for us. We could just move the contents of the temporary copy into the destination, but what of concern two?
We have a destructor that handles disposal, so why not use it? If you swap the destination's contents for the temporary's contents, the destruction of the temporary makes sure destination's original are released correctly without having to write new code or duplicate existing code.
Note that Copy and Swap can be heavier-weight than you really need, but it never fails (assuming the functions it relies on are correct), and that makes it a great place to start.
Been using boost's disjoint_set. It has a copy constructor. To my understanding, it uses pointers that are handed over during the constructor call to access it's data and it doesn't manage memory allocation on its own. Therefore, when you make a copy, the actual data (unlike when you copy a std::vector<T>), isn't copied. You get two seemingly separate instances (cause you aren't using a reference) that access and modify the same data. This seems haphazard and the use case is not clear.
So the question is, why would you say that disjoint_set's copy constructor is useful and why would you make a copy constructor that returns a shallow copy of an instance?
you mean this one: inline disjoint_sets(const self& c) : rank(c.rank), parent(c.parent) {}? Its not clear here whether its shallow or deep copy. rank and parent are of template types : class RankPA, class ParentPA, so its up to the client of this template whether copy should be shallow or deep.
why would you make a copy constructor that returns a shallow copy of an instance?
its dangerous when you have dynamically allocated memory, instead you might consider using move semantics.
What happens (exactly) if you leave out the copy-constructor in a C++ class?
Is the class just memcpy'd or copied member wise?
The class is copied member-wise.
This means the copy constructors of all members are called.
The default copy constructor is made mebmber wise.
The same member-wise approach is also used for creating an assignment operator; the assignment operator however is not created if the class has reference members (because it's impossible to rebind a reference after construction).
You get the default copy that copies the contents from one object into the other one. This has the important side effect that every member containing a pointer is now shared between the original object and the copy.
Notice that with a member-wise copy, if you have allocated any memory, your data structures will share that memory allocated - so it is important, if you want to create a deep (independent) copy of data to create a copy constructor for structures which allocate memory. If your structure is not allocating memory, it is less likely to really require a copy constructor.
However, if you implement the copy constructor, don't forget the Rule of Three: copy constructor, assignment operator, destructor. If one is implemented, all three must be implemented.
Regards,
Dennis M.
This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 10 years ago.
Say I've got a class where the sole data member is something like std::string or std::vector. Do I need to provide a Copy Constructor, Destructor and Assignment Operator?
In case your class contains only vector/string objects as its data members, you don't need to implement these. The C++ STL classes (like vector, string) have their own copy ctor, overloaded assignment operator and destructor.
But in case if your class allocates memory dynamically in the constructor then a naive shallow copy will lead to trouble. In that case you'll have to implement copy ctor, overloaded assignment operator and destructor.
The usual rule of thumb says: if you need one of them, then you need them all.
Not all classes need them, though. If you class holds no resources (memory, most notably), you'll be fine without them. For example, a class with a single string or vector constituent doesn't really need them - unless you need some special copying behavior (the default will just copy over the members).
The default copy constructor will copy the vector if it is declared by value. Beware if you stored pointers in your vector, in such a case, you need to provide specific behaviour for copy/assignement/destruction to avoid memory leaks or multiple delete.
I can think of a few cases when you need to write your own Big Three. All standard containers know how to copy and destroy themselves, so you don't necessarily need to write them. Here's how to know when you do:
Does my class own any resources?
The default copy semantics for pointers is to copy the value of the pointer, not what it points to. If you need to deep copy something, even if it's stored inside a standard container, you need to write your own copy constructor and assignment operator. You also need to write your own destructor to properly free those resources.
Might someone inherit from my class?
Base classes need a destructor. Herb Sutter recommends making them either public and virtual (most common case) or protected and non-virtual, depending on what you want to do with them. The compiler-generated destructor is public and non-virtual, so you'll have to write your own, even if it doesn't have any code in it. (Note: this doesn't imply you have to write a copy constructor or assignment operator.)
Should I prevent a user from copying objects of my class?
If you don't want the user to copy your objects (maybe that's too expensive), you need to declare the copy constructor and assignment operators either protected or private. You don't have to implement them unless you need them. (Note: this doesn't imply you have to write a destructor.)
Bottom line:
The most important thing is to understand what the compiler-generated copy constructor, assignment operator, and destructor will do. You don't need to be afraid of them, but you need to think about them and decide if their behavior is appropriate for your class.
No but there are a number of reasons why you shouldn't allow the compiler to auto generate these functions.
In my experience it is always best to define them yourself, and to get into the habit of making sure that they are maintained when you change the class. Firstly you may well want to put a breakpoint on when a particular ctor or dtor is called. Also not defining them can result in code bloat as the compiler will generate inline calls to member ctor and dtor (Scott Meyers has a section on this).
Also you sometimes want to disallow the default copy ctors and assignments. For example I have an application that stores and manipulates very large blocks of data. We routinely have the equivalent of an STL vector holding millions of 3D points and it would be a disaster if we allowed those containers to be copy constructed. So the ctor and assignment operators are declared private and not defined. That way if anyone writes
class myClass {
void doSomething(const bigDataContainer data); // not should be passed by reference
}
then they'll get a compiler error. Our experience is that an explicit become() or clone() method is far less error prone.
So all in all there are many reason to avoid auto generated compiler functions.
those container will need a "copy constructible" element, and if you don't supply the copy constructor, it will call default copy constructor of your class by deducing from your class members (shallow copy).
easy explanation about default copy constructor is here : http://www.fredosaurus.com/notes-cpp/oop-condestructors/copyconstructors.html
it is so with destructor, the container need to have access to your destructor or your default class destructor if you don't provides one (ie. it will not work if you declare your destructor as private )
you need to provide them if you need them. or possible users of your classes. destructor is always a must, and copy constructors and assignment operator are automatically created by compiler. (MSVC at least)
When ever you have a class that requires deep copies, you should define them.
Specifically, any class which contains pointers or references should contain them such as:
class foo {
private:
int a,b;
bar *c;
}
Subjectively, I would say always define them, as the default behavior provided by the compiler generated version may not be what you expect / want.
Not for strings or vectors, since the trivial constructors / destructors etc, will do fine.
If your class has pointers to other data and need deep copies, or if your class holds a resource that has to be deallocated or has to be copied in a special way.