C++ function argument passed by value - c++

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.

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

Copy constructor for object with vector as member variable

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.

What happens when an object is left uninitialized during a copy constructor or in a assignment operator?

Suppose I have a vector object as one of the attributes and I do't initialize it in the copy constructor, what will happen then?
Also if I do this for any other object which does't have a default constructor, then what will happen?
Suppose I have a vector object as one of the attributes and I do't initialize it in the copy constructor, what will happen then?
I suppose you are pertaining to initializing at the constructor initializer list. If that is so, the default constructor will be called, which you seem to have already answered here...
Also if I do this for any other object which does't have a default constructor, then what will happen?
Your program will not run. More specifically, the compiler will shoot out an error, indicating that you're trying (or implicitly trying) to use that object's non-existing or inaccessible constructor. Try it to see for your self ;).
A way (read: not really the way) to get-around these types of objects is to have them dynamically allocated, that is, use std::unique_ptrs of them. In this way, you could delay their construction when the necessary arguments have been obtained. A better way though, if you can and you should, is to augment or wrap the class of the object to incorporate move semantics. With move semantics, you could eliminate that "delayed-construction-because-i-don't-yet-have-the-necessary-arguments" problem. The default constructor would leave the object's state uninitialized, i.e. unusable but re-initializable using a move/copy constructor. A great example for this is std::thread.
Copy constructors are no different from other constructors. Class members that are not explicitly initialized inside a constructor are default-initialized, which means that members of class type are default constructed, each element of array members is default-initialized, and no initialization is otherwise performed. If a class member doesn't have a default constructor and you don't initialize it in the copy constructor, the compiler will report an error.
(If you don't supply a copy constructor at all, the compiler will generate one for you that will copy-construct every non-static data member and base class subobject, if doing so is legal.)
As for assignment, class members not assigned to will simply retain their value before assignment.
Here's the relevant documentation. In particular,
Before the compound statement that forms the function body of the constructor begins executing, initialization of all direct bases, virtual bases, and non-static data members is finished. Member initializer list is the place where non-default initialization of these objects can be specified. For members that cannot be default-initialized, such as members of reference and const-qualified types, member initializers must be specified.
So, if your custom-defined copy constructor doesn't end up copying a vector member, then your copy will be incorrect, since the vector will end up being default constructed. The C++ program will be entirely valid syntactically - the copy constructor will simply not be "correct". This applies in general to all default constructible members. If you have a member which isn't default constructible, then the code will simply not compile.

What the proper way to return a copy of yourself inside yourself?

Node*Clone(){
numClones++;
Node*cloned=new Node(*this);
return cloned;
}
I have a default constructor (taking no arguments) and I have no declared copy constructors, so I'd expect this to simply copy the entire contents of the memory of *this and return a pointer to it.
However, I am getting error on the new line above:
Call to implicitly deleted copy constructor
Two possible issues but I don't think they should affect this:
this has a unique_ptr attached to it. That is it contains a container of unique_ptr and is itself stored in another container of unique_ptr. But I am not moving that pointer, I am creating new object not attached to the prior object, right?
this is actually a subclass of Node but I want to return a pointer to a base class
As Jeffrey said, std::unique_ptr cannot be copy-constructed.
Also your Clone methods is not logically correct. Because you are instantiating a Node object there - a base class. So it will not be a copy actually
As a solution you may declare a Clone method in the base class and make in pure virtual:
class Node
{
virtual Node * Clone() const = 0;
}
And make your subclasses implement it
PS: don't forget about virtual or protected dtor in the interface
The error message "Call to implicitly deleted copy constructor" means that your class, one of its base classes and/or some of the data members of that class or any of its base classes are declared as non-copyable (or are treated as non-copyable by the compiler which may happen, for example, when at least one of data members is a reference). Therefore, compiler cannot come up with a "default" copy constructor that you are attempting to call with new Node(*this);
The proper way in such a case is to actually find what objects exactly are non-copyable and either make them copyable so that compiler could create an implicitly defined copy constructor, or implement your very own "copying logic" and not use a copy constructor.
Another alternative is to use some sort of a "smart" pointer pointer (i.e. std::shared_ptr). But in that case you get a shallow copy instead of a deep copy.
Since you are doing a copy of yourself, I would really suggest you implement a copy constructor. It's best practice to control, plus if you add memory points in the class, you will really mock things up..
Don't rely on this in your case, here is why not:
Conditions for automatic generation of default/copy/move ctor and copy/move assignment operator?
The problem is caused by your attempt to copy construct a std::unique_ptr (by copying a Node) which, by definition, does not have a copy constructor.
You probably meant to use std::shared_ptr.

Can a object be passed as value to the copy constructor

I have some confusion with this "Can a object be passed as value to the copy constructor"
The compiler clearly rejects this, which means it is not possible.
Can you help me understand this?
class Dummy{
Dummy(Dummy dummy){ // This is not possible
}
};
Then why is it said that "Copy constructor will lead to recursive calls when pass by value is used."
This is because in order to pass by value, you need to COPY the object. Therefore, you are passing in a copy of the object, in the definition of how to copy it.
Effectively what really happens if this trap is not there, is your copy constructor will call your copy constructor to create a copy, which will call your copy constructor to create a copy, which will call your copy constructor to create a copy, ...
No.
As the error says, it will lead to recursive calls of the copy constructor. The copy constructor is used to copy an object. You need to make a copy of an object when it is passed by value.
So, if you could have such a constructor, you would need to invoke the copy constructor to copy the object you pass to the copy constructor, ad infinitum.
The standard specifically says (12.1/10 Constructors):
A copy constructor for a class X is a constructor with a first parameter of type X& or of type const X&
So it can't take a value parameter - it must be a reference.
If you think about if for a moment, it should be clear why: to pass a value parameter, the compiler must make a copy... It needs to invoke the copy constructor to do so.
When a parameter is given by value, the compiler needs to copy an object first (in order create the instance which will be the argument). So for your copy constructor to be called, the compiler needs to make a copy of the object in advance.
Usually the copy constructors are defined in such a way:
Dummy(const Dummy& dummy)
{
// This is possible
}
This way, you don't ask for a separate copy of the object for the constructor, you just give a reference to an existing copy (and promise not to change that copy as well).
Then why is it said that "Copy constructor will lead to recursive calls when pass by value is used."
Because in order to pass an object to that copy constructor by value, you might need to copy-construct it first (because the passed-by-value parameter is a temporary copy of the original object passed).
Though the answer was already given, I just wanted to clarify, since I see the same questions repeated.
Dummy(Dummy dummy); is not a copy constructor. Copy constructor can either be of form Dummy(const Dummy&); or Dummy(Dummy&); The original one is clearly prohibited by the Standard.
Then you are asking:
Then why is it said that "Copy
constructor will lead to recursive
calls when pass by value is used."
Diagnostic message is not mandated by the standard, rather your compiler chose those words to explain why it couldn't possibly work.