Why do we pass object of a class by reference. When I remove ampersand (&) I get following error.
"Copy constructor of class A may not have parameter of type A"
What does this mean? may be compiler is not considering given a copy constructor and using default one.If this is that case why default one is being called. In short why we use ampersand and what will happen? if we don't.
class A
{
public:
A()
{
}
A(A& tmp)
{
id = 2*tmp.id;
}
public:
int id;
};
int main()
{
A obj;
obj.id = 10;
A obj1(obj);
cout << obj1.id;
}
In C++, functions can take their parameters by value or by reference. If they take their parameters by value, that value must be copyable. If a copy constructor could take its parameter by value, then you would need a copy constructor to pass it its parameter, which would cause an endless loop.
Consider:
class MyInt
{
int m;
public:
MyInt(int i)
{
m = i;
}
MyInt(MyInt j)
{
j.m++;
m = j.m;
}
};
MyInt a(1);
MyInt b(a);
How can the compiler make this work? If it uses the default copy constructor, then why would it ever need to call my constructor? And if it uses my constructor, how does it prevent a.m from being incremented (which is clearly wrong, a should not be changed when it is passed by value) given that there's no code to give the constructor its own copy?
Imagine what would happen if you don't:
1) The parameter is now passed by value to the copy constructor
2) In order to pass it by value it invokes the copy constructor
3) Goto 1
There are three ways to pass variables into functions/methods in C++: Pass by value, pass by address, and pass by reference (which is actually pass by address in a pretty wrapper). Pass by address and pass by reference are the simplest in that what gets passed into the underlying function/method is actually the memory address of where the object your passing lies. In order to pass by value, though, a copy of the source object must be made. That's the job of the copy constructor.
In order for the copy constructor to accept an instance of A, you must be able to make a copy of A, which requires a copy constructor, a recursive requirement.
It's the copy constructor that's called when you pass an object by value.
So if your copy constructor requires the instance to be copied before it can run, how can it ever run?
The ampersand tells it to pass it by reference, so no copy is made.
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.
I have read copy constructor is called when "Copy an object to return it from a function."
So I understand the copy constructor is called whenever we return a object is my understanding correct?
If yes, then whenever we return an object the constructor will be called. So, If we were in a mid of program copy constructor will be called. Then values will be assigned to the data member of the class. So the existing value will be replaced?
If no, what is the meaning of the sentence?
SRC: Tutorial point
#include <iostream>
using namespace std;
class demo
{
public:
int rate;
demo(int init_rate);
demo( const demo &obj_passed);
demo display();
};
demo::demo(int init_rate)
{
cout << "\nNormal Construtor" << endl;
rate=init_rate;
}
demo::demo(const demo &obj_passed) // Copy Constructor
{
cout << "\nCopy constructor" << endl;
rate=obj_passed.rate;
}
demo demo::display()
{
demo temp(10);
temp.rate=45;
return temp; //copy constructor is not called here
}
int main( )
{
demo obj1=obj1.display();
return 0;
}
and output is
Normal Constructor
Suppose T is the type of the object, so we have a function:
T foo() {
T returnvalue;
// do some stuff to the return value
return returnvalue;
}
And some code that calls it:
T t = foo();
Then returnvalue is an object local to the function foo. t is an object local to the function that calls foo. Finally, "the return value of foo" is a temporary object. All three objects have type T.
Nominally, returnvalue is copied to the temporary object, and then the temporary object is copied to t, so the copy constructor could be called twice. That's what your reference is talking about. No values are replaced, the copy constructor is called in order to intialize one object as a duplicate of another, separate object of the same type.
However, it is not so simple as the copy constructor always being called when an object is returned. In this example the C++ implementation is permitted to optimize by a mechanism called "copy constructor elision", in which it actually uses the same location for all three objects, and simply omits the copying. So in practice for this code you could see the copy constructor called 0, 1 or 2 times.
That's for C++03. In C++11 there are circumstances (again, my example is one of them) in which the move constructor is called in preference to the copy constructor. So in C++11 the copy constructor is guaranteed not to be called if T has a move constructor. Again, the moves are eligible for elision, so you might see 0, 1 or 2 of them.
You seem to be confused about the meaning of a copy constructor. A copy constructor is used to create a new object. So a copy constructor does not replace any values, it copies old values to a new object.
Whenever you return a local object of a function, the compiler tends to keep and redirect the local object to the place you return(so the local object won't be deleted and compiler need not to create another object to copy the detail of the local object.)
After the statement finishes(;),the local object is then deleted.
On the other hand,if you return a formal parameter,compiler will copy the corresponding argument(with copy constructor),then return the clone of the argument.
I am learning C++ and was reading copy constructor from the C++: The Complete Reference. The books says that
It is permissible for a copy constructor to have additional parameters as long as they have default arguments defined for them. However, in all cases the first parameter must be a reference to the object doing the initializing.
But I am confused that how we are going to pass those additional parameters? I am sure there should be some way which is not given in the book and which I am unable to figure out. Can anyone help me out?
EDIT:
Also is it possible to pass these extra parameters in all three cases i.e.
When one object explicitly initializes another, such as in a declaration
When a copy of an object is made to be passed to a function
When a temporary object is generated (most commonly, as a return value)
Here is a simple example:
class A {
//...
public:
A (const A&, bool deep = false) {
if (!deep) { /* make a shallow copy */ }
else { /* make a deep copy */ }
}
};
void foo (A x) { /*...*/ }
A bar () { /*...*/ return A(); }
A a_var;
In this example, the parameter is defaulted to false, meaning the default copy constructor will be shallow.
A b(a_var); // b gets a shallow copy of a
foo(b); // foo() receives a shallow copy
However, it would be possible to effect a deep copy by passing in true in the second parameter.
A b(a_var, true); // b gets a deep copy of a
foo(A(b, true)); // foo receives a shallow copy of a deep copy
Similarly, for a function returning an A, the returned copy would be shallow, since it is using the default, but the receiver can make it deep when it receives it.
A b(bar()); // shallow
A b(bar(), true); // deep
Remember when you define a copy constructor, it is likely to mean you will need to define a destructor and overload the assignment operator (the rule of three).
Think of it this way: there is only the notion of constructor. When the compiler decides a copy needs to be made, it looks for a constructor that can be called by passing in a single object of type T. Because of this special use case, we conventionally call the constructor chosen a "copy" constructor.
Consider the following :
class A
{
public:
int xx;
A(const A& other)
{
cout << "A cctor" << endl;
/* do some stuff */
}
A(int x) : xx(x) {} /* conversion constructor */
};
int main()
{
A a = 1;
A other = a;
return 0;
}
Is it right to say that CCtor converts from const to non-const in this case (and also in general) ?
Thanks ,Ron
A copy constructor creates a new copy of an existing object, that object may or may not be const. The const in A::A(const A& other) just says we are not going to change other in the copy ctor. Indeed if you attempt to modify other inside the ctor the compiler will moan at you.
The created object also may or may not be const depending on how you declare it.
No idea what you mean. A(const A&) is a typical copy-ctor, which has a "read-only" access to its only argument. If you pass anything const, everything is fine. If you pass anything non-const, for ctor it becomes const. A a = 1 is a conversion ctor, as you said. A other = a is a copy ctor. What's the question?
Regarding your question's title, in C++ there's no fair way to convert const to non-const.
class A
{
public:
int xx;
A(const A& other)
{
cout << "A cctor" << endl;
/* do some stuff */
// other is const here - you can only call its
// const methods and read all its data members
}
A(int x) : xx(x) {} /* conversion constructor */
// at this point, x is not const, but it's a copy
// of an object you've passed here, not the object itself
// you can change x, it just doesn't matter - you
// change the copy
};
int main()
{
A a = 1; // a is not const, 1 is passed "by value", since it's primitive type
A other = a; // a is not const, other is not const, a is passed by const reference
return 0;
}
Constructor initializes a new copy. And there is no problem in copying from a constant.
No conversion is involved.
What do you mean by CCtor converts from const to non-const?
If you mean, the non-const object gets created from the const object by invoking the copy-constructor, then yes. But that doesn't mean the const-object itself becomes non-const inside the copy-constructor (or at the call site). It only means that the newly constructed object is created by copying the existing object which is passed as const reference to the copy-constructor.
No the copy constructor creates an copy of the class object by taking another class object as the parameter.
Since in order to construct the new object being passed as parameter is not required to be modified it it passed as an const.
No, it's not converting to a non-const object. Consider this:
A a(42);
const A another = a;
Here, another is a const object, created from a non-const object.
More important, however, is that a constructor creates a new object from an existing one. Whether that new object is const or not does not depend on the existing object. All four possible combinations of const/non-const old/new objects are possible.
In the sense that the A(int) constructor converts from int to A, yes it's true that your copy ctor A(const A&) "converts" from const A to A. For that matter it also "converts" from non-const A to A, since the const reference parameter can bind to either.
And since the same constructor is used to create a const object as to create a non-const one, that copy ctor can also "convert" from A or const A to const A.
I've used "convert" in quotes just because converting from a type to itself or a cv-qualified version of itself is perhaps a confusing use of the term, normally you just call that "copying" rather than conversion.
The constructor parameter can bind to an instance of a derived class of A too, so you might say that it converts derived classes to A. That's normally called "slicing".
Strictly speaking it's not the copy ctor itself that converts anything, but a conversion to A (whether a cast or an implicit conversion) does depend on using a matching constructor. So I suppose the constructor can claim a large part of the credit.
i m trying to make a simple program ( & yes , it is a homework ) that can generate Dates , & like most of normal people : i made my Class attributes private , i tried to send the same type that i m working on to the constructor but the complier have not accept it , i did some research & i found out that in cases like that people generously send a const "type" reference to the constructor witch meant to me that have not understand OOP well
so why do we have to send the const " type " reference instead of just the types name to the constructor ? & please give me some links or websites for beginners
here is a peace of my Code :
class Date {
int d ;
int m ;
int y ;
public :
Date();
Date(int , int , int);
Date(const Date &);// my question is : why do we have to write this instead of Date( Date )
};
PS : sorry for my English
To paraphrase our question:
why do we have to write Date(const Date &) instead of Date(Date)?
I'm going to split this into two parts, the first answering why a copy constructor needs to take its argument per reference, the second why this needs to be a const reference.
The reason a copy constructor needs to take its argument per reference is that, for a function that's taking an argument per copy void f(T arg), when you call it f(obj), obj is copied into arg using T's copy constructor. So if you want to implement the copy constructor, you'd better not take the argument by copy, because this would call the copy constructor while invoking it, leading to an endless recursion. You can easily try this yourself:
struct tester {
tester(tester) {std::cout << "inside of erroneous copy ctor\n";}
};
int main()
{
tester t1;
std::cout << "about to call erroneous copy ctor\n";
tester t2(t1);
std::cout << "done with call erroneous copy ctor\n";
return 0;
}
That program should only ever write one line and then blow the stack.
Note: As Dennis points out in his comment, actually this program is not guaranteed to compile, so, depending on your compiler, you might not really be able to try it.
Bottom line: A copy constructor should take its argument by reference, because taking it per copy would require the copy constructor.
That leaves the question of why it is const T& and not simply T&? In fact, there are two reasons for that.
The logical reason is that, when you invoke the copy constructor, you do not expect the object copied from to change. In C++, if you want to express that something is immutable, you use const. This tells users that they can safely pass their precious objects to your copy constructor, because it won't do anything with it except read from it. As a nice side effect, if you implement the copy constructor and accidentally try to write to the object, the compiler throws an error message at you, reminding you of the promise made to the caller.
The other reason is that you cannot bind temporary objects to non-const references, you can only bind them to const references. A temporary object is, for example, what a function might return:
struct tester {
tester(tester& rhs) {std::cout << "inside of erroneous copy ctor\n";}
};
tester void f()
{
tester t;
return t;
}
When f() is called, a tester object is created inside, and a copy of it is then returned to the caller, which might then put it into another copy:
tester my_t = f(); // won't compile
The problem is that f() returns a temporary object, and in order to call the copy constructor, this temporary would need to bind to the rhs argument of tester's copy constructor, which is a non-const reference. But you cannot bind a temporary object to a non-const reference, so that code won't compile.
While you can work around this if you want (just don't copy the temporary, but bind it to a const reference instead, which extends the temporary's lifetime to the end of the reference's lifetime: const tester& my_t = f()), people expect to be able to copy temporaries of your type.
Bottom line: A copy constructor should take its argument by const reference, because otherwise users might not be willing or able to use it.
Here's one more fact: In the next C++ standard, you can overload functions for temporary objects, so-called rvalues. So you can have a special copy constructor that takes temporary objects overloading the "normal" copy constructor. If you have a compiler that already supports this new feature, you can try it out:
struct tester {
tester(const tester& rhs) { std::cout << "common copy ctor\n"; }
tester( tester&& rhs) { std::cout << "copy ctor for rvalues\n"; }
};
When you use the above code to invoke our f()
tester my_t = f();
the new copy constructor for rvalues should be called when the temporary object returned by the call to f() is copied to my_t and the regular copy constructor might be called in order to copy the t object from inside of f() to the returned temporary. (Note: you might have to disable your compiler's optimization in order to see this, as the compiler is allowed to optimize away all the copying.)
So what can you with this? Well, when you copy an rvalue, you know that the object copied from is going to be destroyed after the call to the copy constructor, so the copy constructor taking an rvalue (T&&) could just steal the values from the argument instead of copying them. Since the object is going to be destroyed anyway, nobody is going to notice.
For some classes (for example, for string classes), moving the value from one object to another could be much cheaper than copying them.
if I understood your question correctly, to avoid making copies/calling constructor of object.
void function(const T&); // does not create new T
void function(T&); // does not create newT, however T must be modifiable (lvalue)
void function(T); // creates new T
for simple types creating new copy is trivial (and often optimized away by compiler).
For complex object, creating new copy may be very expensive.
Hence you pass it by reference.
https://isocpp.org/wiki/faq/references
https://isocpp.org/wiki/faq/ctors
if you are asking why can not do the following:
struct type {
type(type);
};
Is because this would lead to infinite recursion, since constructor depends on itself
you can do this however
struct type {
type(type, int);
};
since this constructor is different from synthesized type(const type&)
http://en.wikipedia.org/wiki/Copy_constructor
In addition to #aaa's answer, I will try to answer the const part. The const part simply means that the object you are passing logically does not change. This makes sense, because when a copy constructor is called with a Date object argument d, d should not be modified at all!
You can remove the const and your code will still work the same way. However, const provides the additional security that you can never modify the variable marked as const. In your case, this means you can not call any of the non-const method of Date. This is enforced by the compiler at compile-time.
Historically this is the reason for introducing references to the language. Here's an explanation:
In C you can pass values to parameters by value (void f(struct custom_type i)) or by pointer (void g(struct custom_type* i)).
With POD values (int, char, etc.) passing by value is not a problem, but if you are looking at complex structures, then the stack grows too quickly by placing entire structures on stack for function calls. That is why in C you tend to pass structures as parameters by pointer, even if the function doesn't modify them.
In C++ there are cases where neither option worked:
passing by pointers involves a counter-intuitive syntax for operators (if you define operator + for a class custom_type writing custom_type a, b, c; a = &b + &c; is counterintuitive as a doesn't get assigned the sum of the addresses. Furthermore if you wanted to be able to assign the sum of the values to a and the sum of the addresses to a, you would have to somehow differentiate between the cases, by syntax).
passing by value is impossible or undesired in the case of copy constructors. In your case, if you have Date(Date d) {} and assignment Date a; Date b(a); what you get is that a copy of a is created just to be passed as a parameter to the constructor of b. This leads to infinite recursion, as creating a copy of a to pass as a parameter involves is the same as Date d = a; b = Date(d);.
For these reasons (and there may have been others) a decision was made to create references: data types that looks syntactically like a value type, but behave like pointers (that is, it points to the value of another variable, but you access it like a variable, not like a pointer).
Regarding the reason why you need const in the declaration, it is so that your constructor will accept temporary objects. As you cannot modify the value of a temporary references if your constructor doesn't accept const& you can only use the copy constructor for non-const stable objects.
That is, if you have:
class Date
{
public:
Date(Date& other); // non-const reference
...
you can write:
Date a;
Date b = a;
but not:
Date someFunction() { return Date(xxx); }
Date a = someFunction(); // someFunction returns a temporary object
neither:
const Date someImportantDate;
Date a = someImportantDate; // cannot pass const value to non-const