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

  • Context: C/C++ 
  • Thread starter Thread starter shivajikobardan
  • Start date Start date
  • Tags Tags
    Parameter Reference
Join the discussion
Ask a follow-up here, or get your own question answered by working scientists, mathematicians and engineers — people, not an autocomplete.
Real named experts · corrections over time · the nuance an AI answer skips
18 replies · 3K views
shivajikobardan
Messages
637
Reaction score
54
TL;DR
copy constructor
Physics news on Phys.org
Not an expert in C, but the top answer simply says this:

1675358045333.png
 
Reply
  • Like
Likes   Reactions: pbuk, aaroman, jedishrfu and 1 other person
shivajikobardan said:
They just throw a big wall of text. I
This is an incredibly weak criticism. If you had specific complaints, we could maybe address them, but "too much trouble for me to read" is on you, not us.

Your options are call by reference and call by value. Call by value works by creating a copy. Your can't do that without a copy constructor, so you can''t do that when writing a copy constructor.
 
Reply
  • Like
Likes   Reactions: Dale, phinds and Wrichik Basu
Wrichik Basu said:
Not an expert in C, but the top answer simply says this:
But why? Can you explain this via this code (or any code of your choice)?
Code:
#include <iostream>
#include <stdlib.h>
using namespace std;
class Complex
{
private:
    int real;
    int img;

public:
    Complex()
    {
        real = img = 0;
    }

    Complex(int r, int i)
    {
        real = r;
        img = i;
    }

    Complex(Complex &c)
    {
        real = c.real;
        img = c.img;
    }

    void putComplex()
    {
        cout << real << "+i" << img<<endl;
    }
};
int main()
{
    system("cls");
    Complex c1;
    Complex c2(3, 5);
    Complex c3(c2);
    c1.putComplex();
    c2.putComplex();
    c3.putComplex();

    return 0;
}

instead of writing complex &c i f I wrote complex c, what difference would've occurred?
 
shivajikobardan said:
instead of writing complex &c i f I wrote complex c, what difference would've occurred?
Have you tried putting a few print statements inside the constructors and then running the program yourself?
 
Wrichik Basu said:
Have you tried putting a few print statements inside the constructors and then running the program yourself?
https://pythontutor.com/visualize.html#mode=edit
I've even tried this visualizer. Once I remove & the code doesn't run at all. Neither does the visualizer works. That's why.
 
shivajikobardan said:
I've read these answers, but most of them aren't satisfactory. They just throw a big wall of text. I get they're trying to say something about infinite recursion, but I'm failing to get proper explanation for it with diagrams, or even code.
The very first paragraph at the page you linked to says this:
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...
Hardly a wall of text, but what it's saying is that there is a difference in C and C++ between parameters that are passed by value and those that are passed by reference. Before you can understand relatively complex topics such as copy constructors in C++, you need to understand these more basic concepts.

I'm somewhat surprised that you have jumped from writing UI code that uses CSS and HTML and whatever into much more complex languages. You need to crawl before you can walk, and you need to walk before you can run.
 
Reply
  • Like
Likes   Reactions: Wrichik Basu and Vanadium 50
A few point:
  • Why do you want the components of your complex numbers to be integers and not floating point?
  • Why do you not want to take advantage of the scope resolution features of the language? (e.g. Complex::Complex, and using namespace std.)
  • If you are wondering what would happen if you made a change to the code, try it! It has got to be faster than asking us. I suspect it will throw a compiler error, but try it.
 
Write down a long random number on a piece of paper. Now try copy this number to another piece of paper without letting your finger slide over digits of the first number or event looking at them. Impossible right? You need to look at something (i.e. refer to it) in order to copy it.

Alternatively, in case you have a grasp on the difference between a value and a pointer to a value, then know that in C++ a reference can be thought of as a pointer that simply always have to point at something (it can't, like pointers can, legally point at nothing).
 
Reply
  • Like
Likes   Reactions: jim mcnamara, Dale and Wrichik Basu
Mark44 said:
I'm somewhat surprised that you have jumped from writing UI code that uses CSS and HTML and whatever into much more complex languages. You need to crawl before you can walk, and you need to walk before you can run.
I must say you're underestimating css.
 
Vanadium 50 said:
  • If you are wondering what would happen if you made a change to the code, try it! It has got to be faster than asking us. I suspect it will throw a compiler error, but try it.
It throws compiler error.
 
Correct me if I'm wrong:
In int main, "complex c3(c2)" creates a copy of c2 and thus passes c2 to copy constructor.

In copy constructor, "complex(complex c)" copy constructor takes c=c2.

So what's the issue with this?

hello guys, please focus on the issue rather than other things. help me solve and learn it.
 
shivajikobardan said:
It throws compiler error.
As it should. Do you understand the error message? Do you understand why it is better to say "The compiler gave an 'incompatible levels of indirection' (or whatever it said) error than just 'it throws a compiler error'.?
 
Reply
  • Like
Likes   Reactions: Dale
Vanadium 50 said:
As it should. Do you understand the error message? Do you understand why it is better to say "The compiler gave an 'incompatible levels of indirection' (or whatever it said) error than just 'it throws a compiler error'.?
that's my question. you can try in compiler yourself.
 
shivajikobardan said:
I must say you're underestimating css.
I know a little bit about CSS and a whole lot about C and C++. IMO C, and even moreso C++, are vastly more complex than CSS. So, no, I don't think I am underestimating the complexity of CSS.
 
Reply
  • Like
Likes   Reactions: aaroman and Vanadium 50
Vanadium 50 said:
As it should. Do you understand the error message? Do you understand why it is better to say "The compiler gave an 'incompatible levels of indirection' (or whatever it said) error than just 'it throws a compiler error'.?

shivajikobardan said:
that's my question. you can try in compiler yourself.
@shivajikobardan, you completely missed the point of @Vanadium 50's comment. He already knew that defining a copy constructor the wrong way (i.e., without a reference to the object being copied) would cause a compiler error. His point was that it's better to specify exactly what the compiler error was than to merely say "it throws a compiler error."
 
Reply
  • Like
Likes   Reactions: Vanadium 50
shivajikobardan said:
I must say you're underestimating css.
I think you are grossly overestimating CSS compared to actual coding languages.
 
Reply
  • Like
Likes   Reactions: Wrichik Basu and Mark44
shivajikobardan said:
Correct me if I'm wrong:
In int main, "complex c3(c2)" first creates a copy of c2 and thus after that passes this copy of c2 to copy constructor.

In copy constructor, "complex(complex c)" copy constructor takes c=c2.

So what's the issue with this?
I corrected what was wrong above in red, and made more explicit what is happening.

The issue with this is the "first creates a copy" part, which by itself would call the copy constructor, which would require creating a parameter copy first, which would call the copy constructor, which would require creating a parameter copy first... and so on.

In theory this could be solved internally by not using the user defined copy constructor in this special case for the parameter to the user defined copy constructor itself, but rather some default copy constructor. But why bother introducing such special cases and exceptions, just to allow something that is inefficient anyway? You should always pass by reference to avoid unnecessary copies.
 
Last edited:
Reply
  • Like
Likes   Reactions: .Scott and shivajikobardan