Two cases which should avoid calling copy constructor - c++

I have learned about three cases about calling the copy constructor
1. A variable is being initialized from an object of the same class
2. A function is called with a value parameter of the class
3. A function is returning a value that is an object of the class
Also textbook says for the above two cases(case2 and 3), to avoid calling copy constructors, use call-by-reference
I have searched for some information but I can't understand exactly.
For example(I made my own code)
class CpClass{
int p;
CpClass(const CpClass &obj){
cout<<"user-defined constructor"<<endl;
p = obj.p;
}
~CpClass(){
cout<<"destructor"<<endl;
}
};
void show1(String &s)
{ cout << "show1 : " << s.p; }
void show2(String s)
{ cout << "show2 : " << s.p; }
int main(){
CpClass c1(10);
CpClass c2(c1);
show1(c2);
show2(c2);
};
I found some information about this.
First, When we pass an argument which is a class object, if the parameter is reference form not value, it does not call the destructor as soon as the function is ended. It calls destructor when the main function is ended
Second, it call constructor when copy argument whether the parameter form is call by value or call by reference(In code, String &s or String s)
Am I correct or not?

As your posted code does not compile I changed it to:
#include <iostream>
using namespace std;
struct CpClass{
int p;
CpClass(int i){
cout<<"user-defined constructor"<<endl;
p = i;
}
CpClass(const CpClass &obj){
cout<<"user-defined constructor"<<endl;
p = obj.p;
}
~CpClass(){
cout<<"destructor"<<endl;
}
};
void show1(CpClass &s)
{ cout << "show1 : " << s.p; }
void show2(CpClass s) { // Constructor
cout << "show2 : " << s.p;
} // Destructor for s
int main() {
CpClass c1(10); // Constructor
CpClass c2(c1); // Constructor
show1(c2);
show2(c2);
return 0;
}; // Desctructor for c2, c1
Following lines call a constructor
CpClass c1(10);
CpClass c2(c1);
show2(c2);
The first desctructor is called after leaving function
void show2(CpClass s)
The destructors for c2 and c1 are called when leaving main function (in this order)
CpClass &s is syntactic sugar for CpClass * const s. That means that s contains the address of the object and not a copy. Syntactic sugar means that this is a short form and you don't need to dereference.

Related

Constructer Calling order

I know when a constructer is being called, then it gets created in the memory, and when it gets out of the block it gets destroyed unless it's static.
Know I have this code:
#include <iostream>
#include <string>
using namespace std;
class CreateSample
{
private:
int id;
public:
CreateSample(int i)
{
id = i;
cout << "Object " << id << " is created" << endl;
}
~CreateSample()
{
cout << "Object " << id << " is destroyed" << endl;
}
};
void fuct()
{
CreateSample o1(1);
static CreateSample o2(2);
}
CreateSample o3(3);
void fuct2(CreateSample o);
int main()
{
fuct();
static CreateSample o4(4);
CreateSample o5(5);
fuct2(o5);
return 0;
}
void fuct2(CreateSample o)
{
CreateSample o6 = o;
}
and my concern is in object o5, why it's getting called once and gets destroyed 3 times?
When you wrote fuct2(o5); you're calling the function fuct2 and passing the argument by value. This means a copy of the argument will be passed to the function using the implicitly defined copy constructor. Thus you get the 2nd destructor call corresponding this object o.
Moreover, in fuct2 you have CreateSample o6 = o; which will also use the implicitly defined copy constructor to create o6. Thus you will get a third call to the destructor corresponding to this o6.
You can confirm this for yourself by adding a copy ctor as shown below:
class CreateSample
{
//other code here
public:
CreateSample(const CreateSample&obj): id(obj.id)
{
std::cout<<"Copy ctor called"<<std::endl;
}
};
And the output you will get is:
Object 5 is created <------ctor called for o5
Copy ctor called <------copy ctor called for parameter o
Copy ctor called <------copy ctor called for object o6
Object 5 is destroyed <------destructor called for o6
Object 5 is destroyed <------destructor called for o
Object 5 is destroyed <------destructor called for o5
Demo
Though in this particular example you don't strictly require a custom copy constructor or a custom copy assignment operator, they may be needed in other situations. Refer to the rule of three.
CreateSample o5(5); calls the constructor CreateSample(int). fuct2(o5); and CreateSample o6 = o; call the implicitly-defined default copy constructor CreateSample(CreateSample const&). All three of these variables (o6, o, and o5) call the destructor ~CreateSample() when their scope is exited.
The fix is to follow the rule of three and also define a copy constructor and copy-assignment operator:
class CreateSample
{
// ...
CreateSample(CreateSample const& o) {
id = o.id;
cout << "Object " << id << " is copy-constructed" << endl;
}
CreateSample& operator=(CreateSample const& o) {
cout << "Object " << id << " is copy-assigned from " << o.id << endl;
id = o.id;
return *this;
}
}
Demo on Compiler Explorer

why the constructor and destructor of the same class object are implicitly called multiple times

English is not my native language,so please forgive me for my grammar problems.
When I run my program, I find that class constructors are called when defining objects and explicitly calling constructors。After calling the constructor and after leaving the scope, the destructor is called twice。
#include<iostream>
class test {
private:
int a;
int b;
int c;
public:
test(int first = 0, int second = 0, int third=0 );
void show();
~test();
};
void test::show() {
std::cout << this->a<<"\n";
}
test::test(int first , int second , int third ) {
this->a = first;
this->b = second;
this->c = third;
std::cout << "Construct\n";
}
test::~test() { std::cout << "destruct\n"; }
extern test myclassone;
#include <iostream>
#include "myhead.h"
test myclassone;
int main()
{
std::cout << "begain\n";
{
std::cout << "mid\n";
myclassone = test(1,1,1);
std::cout << "mid\n";
myclassone.show();
}
std::cout << "end\n";
}
The output of this program is
Construct
begain
mid
Construct
destruct
mid
1
end
destruct
In my expectation, constructors and destructors will only be called once. But what's puzzling is that according to the output, they were called twice.
I've googled this question, and many of the answers have not explained why the constructor is called when the object is defined, and why the destructor is called immediately after the constructor is called
Your program runs as follows:
The constructor is called for the global object test myclassone;.
main() is called.
begain and mid are printed.
The constructor is called for the temporal object test(1,1,1).
The temporal object is assigned to the global object.
The destructor is called for the temporal object test(1,1,1).
mid is printed.
myclassone.show() is called.
end is printed.
Return from main().
The destructor is called for the global object test myclassone;
Therefore the constructor and destuctor are called once for each objects and called twice in total.

Not understand some C++ syntax

Helo, I'm new to C++ programming.
I'm not understanding about these line of code...
SomeClass someClassObject(35);
...
someClassObject = SomeClass(46);
first of all,what does "someClassObject = SomeClass(46)" does? Is it like what pointer of SomeClass E.G.: "someClassObject = new SomeClass(46)" does but on stack?
No pointers are involved here. SomeClass(46) constructs a temporary object, typically on the stack. This is followed by an assignment to the variable someClassObject. The exact semantics of this assignment can be user-defined by overloading the assignment operator.
PS: Note the missing semicolons at the end of your statements.
SomeClass(46) constructs a new instance of SomeClass on the stack, by calling the constructor passing the number 46 to it.
someClassObject = some instance of SomeClass call the operator= on someClassObject.
Unless the constructor is declared explicit it could also have been written as:
someClassObject = 46;
Take a look at this example: http://ideone.com/7kgWob pasted below:
#include <iostream>
using namespace std;
class SomeClass
{
private:
int i = 0;
public:
SomeClass() { cout << "default constructor\n"; };
SomeClass(int val) { i = val; cout << "constructor getting int: " << val << '\n'; };
~SomeClass() { cout << "destrucing object having i: " << i << '\n'; };
SomeClass& operator=(const SomeClass& rhs) {
cout << "operator= getting int: " << rhs.i << '\n';
if (this != &rhs) {
i = rhs.i;
}
return *this;
}
};
int main() {
SomeClass a(10);
SomeClass b = SomeClass(20);
SomeClass c(35);
c = SomeClass(46);
return 0;
}
It will output:
constructor getting int: 10
constructor getting int: 20
constructor getting int: 35
constructor getting int: 46
operator= getting int: 46
destrucing object having i: 46
destrucing object having i: 46
destrucing object having i: 20
destrucing object having i: 10
In essence it creates a temporary instance, and sets the current instance to the same value as the temporary (two objects with the same value exists at this point). It then frees the temporary. Since no new is involved it happens on the stack.
SomeClass* someClassObject = new SomeClass(46); you initialized a pointer of type class SomeClass to a dynamic object through calling the constructor that takes an integer.
the second you called the overloaded assignment operator which calls the constructor that takes an integer creating a temporary object thenn assigns it to someClassObject.
don't forget ; it is not arbitrary.

why copy constructor is called at the time of calling overloaded assignment operator?

i am trying to understand the use of constructors and assignment operators. I am trying with this below program.
#include <iostream>
using namespace std;
class myclass {
int x;
public:
myclass (int p) {
cout << "calling constructor" << endl;
x = p;
}
myclass () {
cout << "calling constructor with no arguments" << endl;
x = 0;
}
myclass (myclass &t) {
cout << "calling copy constructor" << endl;
x = t.x;
}
myclass operator=(myclass &t) {
cout << "calling assignment operator" << endl;
x = t.x;
return *this;
}
void show () {
cout << "val = " << x << endl;
}
};
int main() {
myclass a1;
a1.show();
myclass a2 = a1;
a2.show();
myclass a3(a2);
a3.show();
myclass a4(200);
a2 = a4;
a2.show();
return 0;
}
Output:
calling constructor with no arguments // call 1
val = 0
calling copy constructor // call 2
val = 0
calling copy constructor // call 3
val = 0
calling constructor // call 4
calling assignment operator // call 5
calling copy constructor // call 6 i am not able to understand this print line
val = 200
call 1, is done from myclass a1;
call 2, is done from myclass a2 = a1;
call 3, is done from myclass a3(a2);
call 4, is done from myclass a4(200);
call 5, is done from a2 = a4;
but i am not able to get where call 6 is coming from, it is called from the instruction:
a2 = a4;
But, how it will give call to copy constructor?
any help/pointer wil be a great help. I am diving into cpp from c, hence please bear with me.
myclass operator=(myclass &t) {
cout << "calling assignment operator" << endl;
x = t.x;
return *this;
}
The above function returns by value.
Returning by value is one of the cases when copy constructor is called.
Also AFAIK, this is not always true(returning by value calling copy constructor) as some compilers implement return value optimization.
(You copy constructor and assignment operators are slightly malformed: they ought to take a const reference as the argument, and the assignment operator ought to return a reference not a value).
With myclass a2 = a1;, a2 doesn't yet exist. So the copy constructor is called to create a2 using a1.
But with a2 = a4, a2 already exists, so the assignment operator is used to assign a2 to a4.
So the rule is essentially: If an object doesn't exist then it needs to be constructed. Your observed output can be explained by applying this rule.
change it to
myclass& operator=(myclass &t)
then:
calling constructor with no arguments
val = 0
calling copy constructor
val = 0
calling copy constructor
val = 0
calling constructor
calling assignment operator
val = 200
If you return by value, copy ctor will be called.
Return by reference to avoid calling copy ctor.
Your assignment operator returns by value, so there's another copy made when it returns.
That's where the sixth call is coming from.
Typically, an assignment operator returns a reference instead, so that when you return *this, you really do return *this:
myclass& operator=(myclass &t) {
// ^

Copy Constructor

I am new to C++ programming, I got a doubt when I was reading a C++ regarding copy constructor. Why copy constructor will call when we pass object of class to a outside function as pass by value. Please go through my code as below.
#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
class Line
{
public:
int getLength( void );
Line( int len ); // simple constructor
Line( const Line &obj); // copy constructor
~Line(); // destructor
private:
int *ptr;
};
// Member functions definitions including constructor
Line::Line(int len)
{
cout << "Normal constructor allocating ptr" << endl;
ptr = new int;
*ptr = len;
}
Line::Line(const Line &obj)
{
cout << "Copy constructor allocating ptr." << endl;
ptr = new int;
*ptr = *obj.ptr; // copy the value
}
Line::~Line(void)
{
cout << "Freeing memory!" << endl;
delete ptr;
}
int Line::getLength( void )
{
return *ptr;
}
void display(Line obj)//here function receiving object as pass by value
{
cout << "Length of line : " << obj.getLength() <<endl;
}
// Main function for the program
int main( )
{
Line line(10);
display(line);//here i am calling outside function
_getch();
return 0;
}
In the above the I am passing object of class as parameter and display function receiving it as pass by value. My doubt is when I pass object to a function which is not a member of class why copy constructor is calling. if I receive object as reference in display() function[i.e display(Line &Obj)] it is not calling the copy constructor. Please help me what is the difference.
When you pass something by value, the copy constructor is used to initialize the parameter that's passed -- i.e., what's passed is a copy of whatever you give, so of course the copy constructor is used to create that copy.
If you don't want the value copied, pass by (probably const) reference instead.