This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why should the copy constructor accept its parameter by reference in C++?
i know that a copy constructor must have a reference as a parameter, to avoid an 'infinite number of calls' to itself. my question is - why exactly that happens, what is the logic behind it?
CExample(const CExample& temp)
{
length = temp.length;
}
assume your argument to the copy C'tor was passed by value, the first thing the C'tor would have done, was copying the argument [that's what every function, including constructors do with by-value arguments]. in order to do so, it would have to invoke the C'tor again, from the original to the local variable... [and over and over again...] which will eventually cause an infinite loop.
Copy constructors are called on some occasions in C++. One of them is when you have a function like
void f(CExample obj)
{
// ...
}
In this case, when you make a call
CExample x;
f( x );
CExample::CExample gets called to construct obj from x.
In case you have the following signature
void f(CExample &obj)
{
// ...
}
(note that obj is now passed by reference), the copy constructor CExample::CExample does not get called.
In the case your constructor accepts the object to be copied by value (as with the function f in the first example), compiler will have to call the copy constructor first in order to create a copy (as with the function f, again), but... oops, we have to call the copy constructor in order to call the copy constructor. This sounds bad, doesn't it?
See here
"It is a reference because a value parameter would require making a copy, which would invoke the copy constructor, which would make a copy of its parameter, which would invoke the copy constructor, which ... "
Or put a different way a value parameter to the constructor would have to call the constructor to copy the value in the parameter. This new constructor would need to do the same - leading to infinite recursion!
Related
Why use references to the parameters of the copy constructor?
I found a lot of information saying that it is to avoid unlimited calls, but I still can't understand it.
When you pass to a method by value, a copy is made of the argument. Copying uses the copy constructor, so you get a chicken and egg situation with infinite recursive calls to the copy constructor.
Response to comment:
Passing by reference does not make a copy of the object begin passed. It simply passes the address of the object (hidden behind the reference syntax) so the object inside the copy constructor (or any method to which an object is passed by reference) is the same object as the one outside.
As well as solving the chicken-and-egg here, passing by reference is usually (for larger objects - larger than the size of a point) faster.
Response to further comment:
You could write a kind of copy constructor that passed by pointer, and it would work in the same way as passing by reference. But it would be fiddly to call explicitly and impossible to call implicitly.
Declaration:
class X
{
public:
X();
X(const X* const pOther);
};
The explicit copy:
X x1;
X x2(&x1); // Have to take address
The implicit copy:
void foo (X copyOfX); // Pass by value, copy made
...
X x1;
foo (x1); // Copy constructor called implicitly if correctly declared
// But not matched if declared with pointer
foo (&x1); // Copy construcxtor with pointer might (?) be matched
// But function call to foo isn't
Ultimately, such a thing would not be regarded as a C++ copy constructor.
This code:
class MyClass {
public:
MyClass();
MyClass(MyClass c);
};
does not compile. That is, because the second line here:
MyClass a;
MyClass b(a);
should theoretically cause the infinite loop you're talking about - it should construct a copy of a to before calling the constructor for b. However, if the copy constructor looks like this:
MyClass(const MyClass& c);
Then no copies are required to be made before calling the copy constructor.
From this webpage
A copy constructor is called when an object is passed by value. Copy
constructor itself is a function. So if we pass an argument by value
in a copy constructor, a call to copy constructor would be made to
call copy constructor which becomes a non-terminating chain of calls.
Therefore compiler doesn’t allow parameters to be passed by value.
By passing the argument by value the copy constructor calls itself, entering in an infinite 'recursion cycle'. The link above explain pretty well the basic topics about the copy constructor.
This question already has answers here:
What are copy elision and return value optimization?
(5 answers)
Closed 6 years ago.
I was puzzled as why I had to write copy constructor of this one class when I defined a function inside another class with the return type of the first mentioned class.
For example:
class Foo{
// attributes
public:
Foo(){...}
// I had to write the CC
Foo(const Foo& obj){
//...
}
}
class Bar{
// ....
// This is the function
Foo SomeFunction()
{
Foo myVar;
// ....
return myVar;
}
I checked by couting that the copy constructor is actually being called.
I need confirmation though because it would seem more logical to me that the default constructor is called in this situation, like in this line where myVar is created.
I'm a beginner so I'm trying to wrap my head around these calls.
The line
Foo myFunc;
calls the default constructor.
The line
return myFunc;
calls the copy constructor since the return type of the function is Foo. The object returned from the function is not myFunc but a copy of myFunc. myFunc gets deleted when the function returns. The copy is what the calling function gets.
If the compiler is able to use RVO (return value optimization), then myFunc is returned to the calling function, not a copy. In that case, the copy constructor will not get called.
You don't have to write a CC on C++. The compiler should give you one.
And yes, a CC will be invoked in this case since you are trying to pass the return value as a copy.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why should the copy constructor accept its parameter by reference in C++?
Can a object be passed as value to the copy constructor
Consider this piece of code:
class complex{
private:
double re, im;
public:
complex(double _re, double _im):re(_re),im(_im){}
complex(complex c):re(c.re),im(c.im){}
};
When compiled, I got an error message: invalid constructor; you probably meant ‘complex (const complex&)’
In the book C++ Programming Language, it is written that:
The copy constructor defines what copying means – including what
copying an argument means – so writing
complex : complex(complex c) :re(c.re) , im(c.im) { } // error
is an error because any call would have involved an infinite recursion.
Why does this cause infinite recursion? It doesn't make sense.
Passing by value means that the parameter is copied into the function. That calls the copy constructor.
If your copy constructor parameter is pass-by-value... It would call itself... over and over again...
Passing by value (rather than by reference) means a copy needs to be made. So passing by value into your copy constructor means you need to make a copy before the copy constructor is invoked, but to make a copy you first need to call the copy constructor.
When a function is passed with a parameter, local variable is created corresponding to the parameter and is copied with the argument passed on to the function invocation. Hence when the function is invoked, copy constructor of the function will be invoked to copy the argument passed to the invocation to the local variable created. This results in a endless loop.
Where as when a reference is passed on to the function , local variable is not created corresponding to the parameter.
I have a copy constructor that looks like this:
Qtreenode(const QtreeNode * & n) {
x=n->x;
y=n->y;
height=n->height;
width=n->width;
element=n->element;
}
I wrote this a week ago, and I looked back at it today and I was surprised by the line that when called the copy constructor with say swChild=new QtreeNode(*(n->swChild)); The arguement to the cc is a pointer by reference, right? But when I call it, I do (*(n->swChild)), which means the value of that child right? Why does my code work?
That is not a copy constructor. A copy constructor for a class is a constructor that takes a reference of the class's type. Any of the following would be copy constructors, though the second, taking a const reference, is by far the most commonly used:
QTreeNode(QTreeNode&);
QTreeNode(const QTreeNode&);
QTreeNode(volatile QTreeNode&);
QTreeNode(const volatile QTreeNode&);
Since this isn't a copy constructor, the implicitly declared copy constructor is still provided. It is declared as QTreeNode(const QTreeNode& n) and basically just copies each member of the class (i.e., it's a "shallow" copy, not a "deep" copy). It is this implicitly declared copy constructor that is used in your code.
That's not a copy constructor, it's just a regular old constructor. A copy constructor would take a const QtreeNode&, not a const QtreeNode*&.
Since you didn't define a copy constructor, the compiler made one for you. That's the one that is being called in the line swChild=new QtreeNode(*(n->swChild));, since you are passing a QtreeNode and not a pointer to one.
Can I write a copy constructor by just passing in a pointer instead of the const reference? (Would it be ok if I make sure that I am not going to change any values though?)
Like so:
SampleClass::SampleClass(SampleClass* p)
{
//do the necessary copy functionality
}
instead of:
SampleClass::SampleClass(const SampleClass& copyObj)
{
//do the necessary copy
}
Thanks in advance.
Thanks everyone. So, if I write a constructor that takes in a pointer( and thought that's my copy constructor), the compiler would still supply with the default copy constructor in which case my constructor( which i thought was my copy constructor) would not be called and the default copy constructor would be called. Got it.
Yes, you can write a constructor that takes a pointer to the object. However, it cannot be called a copy constructor. The very definition of a copy constructor requires you to pass an object of the same class. If you are passing anything else, yes, it's a constructor alright, but not a copy constructor.
You can write a constructor that takes a pointer as an argument.
But the copy constructor is the name we give a specific constructor.
A constructor that takes a reference (preferably const but not required) of the same class as an argument is just named the copy constructor because this is what it effectively does.
Besides the fact that it would not be a copy constructor and the compiler will generate the copy constructor unless you explicitly disable it, there is nothing to gain and much to loose. What is the correct semantics for a constructor out of a null pointer? What does this add to the user of your class? (Hint: nothing, if she wants to construct out of a heap object she can just dereference the pointer and use the regular copy constructor).
No. Copy constructors must take a reference, not pointer, if it's to be useful for passing-by-value, etc.
By definition, the copy ctor uses a const reference. While there is nothing stopping you from writing a ctor that takes a pointer, it raises some problems not present when using a reference - e.g., what should/can happen if a null pointer is passed in?
A copy constructor needs a reference because a value parameter would require making a copy, which would invoke the copy constructor, which would make a copy of its parameter, which would invoke the copy constructor, which ...
You can write a constructor like that but its not technically a copy constructor. For example the STL containers will still use the compiler generated copy constructor (the compiler generates one because you didn't write one).
The copy constructor is implicitly used in two cases:
When an instance of your class is passed by value to a function.
When an instance of your class is returned by value from a function.
As others have mentioned, you can write a constructor with the signature described (or with a const pointer), but it would not be used in either of the above cases.
You can write a perfectly valid copy constructor, and still be able to pass a reference that is NULL. You can test for NULL, but only if you do not use constructor initialization lists.
Example:
MyClass::MyClass( MyClass const& MyClassCopy )
: somevar( MyClassCopy.somevar ) // <- the init list goes here.
{
// If MyClassCopy is NULL, the initialization above is doomed!
// However we can check for NULL in the constructor body but
// the initialization list must be removed ...
if (&MyClassCopy == NULL ) throw( std::runtime_error("NULL pointer!"));
somevar = MyClassCopy.somevar;
}
// I'll now do some very dangerous programming to
// demonstrate one way that a NULL can get through ...
MyClass* P = NULL;
MyClass A( *P ); // Bang, you're dead!
As far as I know, there's no way to check for a NULL from inside the initialization list, so if you think you could end up with a situation where a NULL gets through, you have to test for it in the constructor body and do the initializing from there.
Don't forget there's a few gotchas with ::operator=() function to be aware of ...