Why should the copy constructor accept its parameter by reference in C++?
Asked Answered
M

10

146

Why must a copy constructor's parameter be passed by reference?

Maletta answered 21/4, 2010 at 19:12 Comment(0)
B
221

Because if it's not by reference, it's by value. To do that you make a copy, and to do that you call the copy constructor. But to do that, we need to make a new value, so we call the copy constructor, and so on...

(You would have infinite recursion because "to make a copy, you need to make a copy".)

Backsword answered 21/4, 2010 at 19:14 Comment(4)
Is there a reason it couldn't be pass-by-pointer to instance?Procyon
Then it is no longer a copy constructor, but just a regular old constructor that happens to accept a pointer.Exegete
@Barry you commonly implement a copy-constructor when the compiler tries to make a copy of an object on its own by calling object o(other_object). But this only works if object has a constructor that takes another object by value or by reference. You already know why passing by value doesn't work, so the only way is passing by reference or const reference. If your "copy-constructor" would take a pointer to an object then the compiler's code would have to be object o(&other_object). So in essence you write a constructor that satisfies what the compiler and users expect.Pood
Another good reason, noted by my compiler, is if you have a base class with pure virtual functions the intialization of this variable by value would not be possibleEnoch
T
74

Because pass-by-value would invoke the copy constructor :)

Tungstate answered 21/4, 2010 at 19:15 Comment(0)
C
27

The alternative to pass-by-reference is pass-by-value. Pass-by-value is really pass-by-copy. The copy constructor is needed to make a copy.

If you had to make a copy just to call the copy constructor, it would be a conundrum.

(I think the infinite recursion would occur in the compiler and you'd never actually get such a program.)

Besides rational reasons, it's forbidden by the standard in §12.8/3:

A declaration of a constructor for a class X is ill-formed if its first parameter is of type (optionally cv- qualified) X and either there are no other parameters or else all other parameters have default arguments.

Cryptography answered 21/4, 2010 at 19:30 Comment(4)
Compilers can happily spit out infinite recursion; I suspect this isn't a special case. However, the program is ill-formed if you declare a copy constructor with a non-reference parameter. So you're right that it shouldn't compile.Exegete
@Dennis: I mean, if you attempted to compile such a program, the compiler would get stuck trying to generate the code. It would not generate a recursive function because the conundrum occurs before the function call, in the caller.Cryptography
Either way, the program is ill formed whether you try to use it or not. Simply defining the constructor is enough to cause the compiler to yell at you.Exegete
@Dennis: Indeed, although that is simply a rule.Cryptography
I
14

It would be infinitely recursive if you passed it in by value

Intentional answered 21/4, 2010 at 19:16 Comment(0)
A
10

whenever you call a function (example: int f(car c)) which takes its arguments other than built-in data types (here car) a requirement to copy the actual object supplied by the caller to the variable in the called function's parameter.
example:

car carobj; f(carobj);

that is, copy carobj to c.

carobj needs to be copied to the parameter c in function f.

To achieve copying, the copy constructor is called.

In this case, function f called using pass by value or in other words, function f is declared to take pass by value.

If function f takes pass by reference, then its declaration is int f(car &c);

In this case,
car carobj; f(carobj);

does not need a copy constructor.

In this case, c becomes the alias of carobj.

Using the above 2 scenarios, for your clarity I am summarizing them as:

  1. If a function is declared to take a parameter as value of a object, then the copy constructor of the object is called.

  2. If a function is declared to take a parameter as "pass by reference", the parameter becomes an alias of the object supplied by the caller. No need of a copy constructor!

Now the question is why pass by reference is required. If copy constructor accepts reference, the receiving variable become aliases of supplied object. Hence, no need of copy constructor (in this case, call to itself) to copy the value in caller supplied object to copy constructor's variable in argument list.

Otherwise, if copy constructor takes the caller supplied object as value, i.e. pass by value, then it needs the copy constructor of the given object; hence, to get the supplied object from caller into our function itself (in this case the copy constructor) we need to call the copy constructor, which is nothing but calling the same function during function declaration.

That's the reason for passing a reference to a copy constructor.

Ancy answered 13/3, 2012 at 0:20 Comment(1)
While you are correct, there were already four answers explaining this, and doing so much more clearly. I don't understand why you thought a fifth answer to this question would be helpful.Kiker
G
7

It is necessary to pass object as reference and not by value because if you pass it by value its copy is constructed using the copy constructor.This means the copy constructor would call itself to make copy.This process will go on until the compiler runs out of memory.

Germinant answered 29/8, 2015 at 15:42 Comment(0)
O
1

It is very essential to pass objects as reference. If an object is passed as value to the Copy Constructor then its copy constructor would call itself, to copy the actual parameter to the formal parameter. Thus an endless chain of call to the copy constructor will be initiated. This process would go on untill the system run out of memory.

Hence, in a copy constructor, the parameter should always be passed as reference.

Obrian answered 29/1, 2014 at 10:7 Comment(0)
G
1

If its not passed by reference then it would pass by value. If the argument is passed by value, its copy constructor would call itself to copy the actual parameter to formal parameter. This process would go on until the system runs out of memory. So, we should pass it by reference , so that copy constructor does not get invoked.

Georgeanngeorgeanna answered 10/3, 2014 at 13:46 Comment(0)
P
1

All the answers are correct but I wonder if any of that can help to a beginner like me who learns via examples. So, here's an example.

Take this code for example:

#include<iostream>
#include<cstring>
using namespace std;

class String
{
private:
    char *s;
    int size;
public:
    String(const char *str)
    {

        size=strlen(str);
        s=new char[size+1];
        strcpy(s,str);
    }
    ~String()
    {
        delete[] s;
    }

    String(const String& old_str)
    {
        size=old_str.size;
        s=new char[size+1];
        strcpy(s,old_str.s);

    }
    void print()
    {
        cout<<s<<endl;
    }
    void change(const char *str)
    {
        delete [] s;
        size=strlen(str);
        s=new char[size+1];
        strcpy(s,str);
    }
};
int main()
{
    String str1("Hello World");
    String str2=str1;

    str1.print();
    str2.print();

    str2.change("Namaste");
    str1.print();
    str2.print();
    return 0;
}

This is the copy constructor:

String(const String& old_str)
        {
            size=old_str.size;
            s=new char[size+1];
            strcpy(s,old_str.s);
    
        }

Imagine we don't pass by reference. ie:

String(const String old_str)
        {
            size=old_str.size;
            s=new char[size+1];
            strcpy(s,old_str.s);
    
        }

Look at the int main() function.

String str2=str1

Again look at the copy constructor(without reference).

String(const String old_str)

That means:

String old_str=str1

It is basically the same thing written in the main() function. Thus, it calls the copy constructor again. The rule of calling copy constructor in C++ is when you've a scenario like this:

ABC a;
ABC b=a;

I hope this helps.

Pericline answered 23/4, 2023 at 17:9 Comment(0)
C
0

A copy constructor defines what copying means,So if we pass an object only (we will be passing the copy of that object) but to create the copy we will need a copy constructor, Hence it leads to infinite recursion.

So, A copy constructor must have a reference as an argument.

Comstock answered 12/8, 2021 at 12:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.