user3205479
user3205479

Reputation: 1523

Behavior of constructors when copy constructor is defined by user

Iam trying to understand copy constructors please understand me how it works.

Case 1

class fruit{
    public: int i;
            fruit(int j){
               i = j;
            }
};

int main(){
   fruit f1 = fruit(2); // works fine when no user defined copy constructor
   return 0;
}

Case 2

class fruit{
    public: int i;
            fruit(fruit &f){
               i = f.i + 1;
            }
            fruit(int j){
               i = j;
            }
};

int main(){
   fruit f1 = fruit(2); // error no matching call fruit::fruit(fruit) why?
   return 0;
}

Case 3

class fruit{
    public: int i;
            fruit(){
               i = 0;
            }
};

int main(){
   fruit f2;
   fruit f1 = fruit(f2); // works fine when no user defined copy constructor
   return 0;
}

Case 4

class fruit{
    public: int i;
            fruit(){
               i = 0;
            }
            fruit(fruit &f){
              i = f.i + 1;
            }
};

int main(){
   fruit f2;
   fruit f1 = fruit(f2); // error no matching call fruit::fruit(fruit)
   return 0;
}
Technically 'fruit(f2)' must be valid because 
f2 can be passed by reference to fruit(fruit &f). right? but why error?

Why do I get error in Case 2 and Case 4? is this because I created user defined copy constructor? If the reason is user defined copy constructor, even compiler provides default copy constructors. like fruit(fruit &) internally So even then copy constructors are available to program provided by compiler. Why it does not raise error in Case 1 and Case 3

I understand all constructors are blocked with = when user defines copy constructor. = can invoke only copy constructor. but there must be one copy constructor to a class may be by user or by compiler. If it is provided by compiler then also it must raise error. but it does not do why?

Upvotes: 0

Views: 60

Answers (2)

ravi
ravi

Reputation: 10733

fruit f1 = fruit(f2);

For fruit(f2) , temporary would be created which cannot be bind to non-const reference. You have to use follwoing copy constrcutor for this to work:-

fruit(const fruit& f)

Upvotes: 1

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385144

This is not a problem specifically related to copy constructors; non-const lvalues references cannot bind to temporaries.

The following code would have compiled:

fruit f1;
fruit f2(f1);

because f1 is not a temporary when you pass it in.

Still, you want temporaries to work, so write your copy constructor like this:

fruit(const fruit& f) {
   i = f.i + 1;
}

Your cases 1 and 3 succeed because the compiler is able to generate its own "default" copy constructor having seen that you did not provide one, which — unlike you — it does correctly. :-)

Upvotes: 2

Related Questions