Copy constructor for object with vector as member variable - c++

I have a class A with a vector<Object> object_list_ as a member variable.
I know that if I had a vector of pointers I would have needed to write a specific copy constructor to achieve a deep copy. However, in this case, as I don't have pointers, when copying an object of type A, the default copy constructor will automatically also call the copy constructors of Object or each element in object_list_ or do I have to write my own copy constructor to do that?

The default copy constructor for your class will call the default copy constructor for each member, in the order they're declared in the class. One rule of thumb is that if you don't need a special destructor, then you don't need to change the copy constructor, copy assignment, move constructor, or move assignment either. (Though deleting them may still make sense, depending on the class).
A vector's copy constructor will make a copy of its elements, using their copy constructors. If those are pointers, it will copy the pointers, which means they'll point at the same data as the origonal vector. 99% of the time this is what you want. Though very rarely you may want to replace your class' copy constructor to make the vector do something else.
It sounds like you don't need to make a copy constructor in your case.

Copy constructors of member variables are called all the way down. So if a default one was generated (and it would be in this case) then it gets called.

Related

What is the use of copy constructor while the same can be done with assignment operator '='?

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).

When to provide user-defined copy constructor and assignment operator?

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.

C++ function argument passed by value

I know that when you call a function this way :
foo(MyClass a)
The object a is being passed by value meaning it's being copied.
My question is how is it being copied?
say my class don't have a copy constructor, so if it is passed using shallow copy than
the object may change inside the function?
Compiler automatically generates the code for the copy constructor and performs member wise copy. The copy constructor which compiler calls does member wise copy which is indeed shallow copy.
It is inadvisable to pass an object by value if a pointer in your class exists. Even if a pointer does not exist, but a dozen other data members exist, they would require a lot of time to get copied.Pass it by reference, and make it const if you dont want its value to be changed.
There are two possibilities.
First: You didn't specify a copy constructor.
In this case the default copy constructor MyClass::MyClass(MyClass const&) will be used. This will attempt to copy construct all of MyClass's member (recursively, as these may have members themselves). If any of these members is not copy constructible your default copy constructor will therefore fail as well (see next point).
Second: You declared the copy constructor private or actually deleted it (in C++11).
In this case, you will not be able to pass anything to this function, because the compiler will require access to a copy constructor, which you denied it. This will lead to compile time errors.
the compiler creates a default copy constructor.

Should we explicitly write a copy constructor if the class member is a vector?

struct myType {
vector<char*> ls;
};
Here ls is holding pointers to char. If a user-defined copy constructor for myType is not provided, will myType's default copy constructor do a deep copy of ls?
Here ls is holding pointer to char. If copy constructor is not provided, will default copy constructor do the deep copy?
The default copy constructor will copy all members – i.e. call their respective copy constructors.1 So yes, a std::vector (being nothing special as far as C++ is concerned) will be duly copied.
However, the memory pointed to by the char* elements inside the vector will of course not, since C++ doesn’t know and doesn’t care what the pointers point to.
But the solution here isn’t to provide a custom copy constructor. It’s to use a data structure instead of raw pointers (char*) which does. And this happens to be std::string (or std::vector<char> depending on the intent).
1 Thus creating a transitive closure of the copy operation – this is how deep copying is generally implemented, but of course an implementor of the copy operation can always break out of it.
will default copy constructor do the deep copy?
Of course not. The compiler cannot know who owns the pointed-to memory.
If deep copy is required, you have to implement the copy constructor and manually copy each char* into new memory for the vector in the copied-to object.
If you use the char* as zero-terminated strings, then you should really use std::string instead. If you do, the default constructor is enough.
No, it will not.
C++ will recursively call the copy ctor of all subobjects. So it will call the copy ctor of the vector, which will in turn call the copy ctor of the char* which will copy the char* by value. C++ will never automatically allocate memory and copy the data. It can't even possibly do that, since it does not know what the data is you are pointing at, and how much it should copy.
When you use strings, you should prefer using std::string, as this will do all the copying for you. If it is some binary data buffer that needs special handling, then you need to do that yourself in your copy ctor (and when you are done, think a moment about if it was really sensible to think about requiring C++ to do that for you).
When you write your own copy ctor, you always should mind the Rule of Three

What happens (exactly) if you leave out the copy-constructor in a C++ class?

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.