snippet 1:
#include<iostream>
using namespace std;
class C{
public:
C(){}
C(const C& c){
cout<<"const copy constructor called"<<endl;
}
};
int main(){
C c1;
C c2 = c1;
return 0;
}
output: const copy constructor called
snippet 2:
#include<iostream>
using namespace std;
class C{
public:
C(){}
C(const C& c){
cout<<"const copy constructor called"<<endl;
}
C(C& c){
cout<<"non-const copy constructor called.\t "<<endl;
}
};
int main(){
C c1;
C c2 = c1;
return 0;
}
output: non-const copy constructor called
snippet 3:
#include<iostream>
using namespace std;
class C{
public:
C(){}
C(const C& c){
cout<<"const copy constructor called"<<endl;
}
C(C c){
cout<<"non-const copy constructor called.\t "<<endl;
}
};
int main(){
C c1;
C c2 = c1;
return 0;
}
output: error: copy constructor must pass its first argument by reference
I am so confused about:
C(const C& c)
, C(C c)
won't cause infinite recursion, why it still doesn't work?Snippet 1: One standard copy constructor with const T&
. Happy world.
Snippet 2:
What you have effectively done is overloaded the copy constructor - one that takes a reference T&
and the other that takes a constant reference const T&
.
Please note: Any constructor for a class T that has one mandatory argument of type T &
or const T &
(it may also have further, defaulted arguments) is a copy constructor.
So, for the compiler, it all just boils down to finding the Best Fit for overload resolution and it is done as:
Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if:
- ....
- S1 and S2 are reference bindings (8.5.3), and the types to which the references refer are the same type except for top-level cv-qualifiers, and the type to which the reference initialized by S2 refers is more cv-qualified than the type to which the reference initialized by S1 refers.
So writing
C c1;
C c2 = c1;
will call the non-const copy constructor since it is a better match, but,
writing,
const C c1;
C c2 = c1;
will call the const copy constructor (you can check) since now the copy constructor with const is the only viable match.
Snippet 3 is just plain wrong for the compiler.
C(C c){
cout<<"non-const copy constructor called.\t "<<endl;
}
You can't have a method with a signature C(C c)
. The compiler thinks that you are trying to write a copy constructor and missed writing the &
and hence reports the error. Remove it and it works fine.
@Unless you have a very good reason, never ever use C(C& c)
for your copy constructor. Don't skip const
because mutating the object from which you are making a copy doesn't make much sense.