At which line is the copy constructor called? - c++

I have a few lines of code and I don't get, why and where the copy constructor is called. Could you explain it to me?
The output is:
CS10
CS99
CC100
Obj10=Obj100
D100
Obj10=Obj99
D99
D10
This is my source code:
#include <iostream>
using namespace std;
class my
{
int m;
public:
my(int i): m(i)
{
cout << "CS" << m << endl;
}
my(const my& c): m(c.m+1)
{
cout << "CC" << m << endl;
}
~my()
{
cout << "D" << m << endl;
}
my& operator=(const my &c)
{
cout << "Obj" << m << "=Obj" << c.m << endl;
return *this;
}
};
my f(my* x)
{
return *x;
}
int main()
{
my m1(10);
my m2(99);
m1 = f(&m2); // creates a new object
m1 = m2; // does not create a new object
}
Why and where is copy constructor called causing the output CC100 and D100?

In this function
my f(my* x)
{
return *x;
}
called in statement
m1 = f(&m2); // creates a new object
the copy constructor is called to copy object *x in the return temporary object.
In fact it looks as
my tmp = *x; // the copy constructor is called
m1 = tmp;

When trying to think about when a copy constructor is called you should keep a few things in mind:
Scope - functions can't see outside of themselves and their associated namespace. If you want to pass a variable to a function you need to save it in the global environment, repush a scoped copy and then operate on it.
When you use passing by reference you operate on the global copy but since in this case you are returning the value that is pointed to and not a pointer you have to push that return value onto the stack separately because it is stored at a different temporary register address that is popped off the stack after you assign it to a permanent location in main. That's where the destructor comes in.
You made a temporary return value to pass the value out of your function so it's got to be deleted because L1, L2, and L3 cache are all prime real estate.
I highly recommend doing a little bit of reading on assembly code operations or even try compiling simple programs into assembly and seeing how the low level languages work under the hood. Cheers!

Related

Assigning a variable to dynamically allocated return value?

I am trying to assign a variable to a return value but the deconstructor is called before the values are assigned to pq. I also get the following error which I'm assuming is an attempt to double delete a variable:
_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
PriorityQueue pq;
pq = FindThroughPaths(a, b);
FindThroughPaths(a, b) returns a PriorityQueue.
I may be getting this error because the return value has dynamically allocated member variables.
I am simply trying to find a way to keep the return value of FindThroughPaths(a, b) within the scope and I do not want to create multiple instances just to access it's members. This is an example of what I would like:
PriorityQueue pq;
pq = FindThroughPaths(a, b);
while (!pq.IsEmpty) {
Path tmp = pq.Dequeue();
std::cout << "\n" << tmp.name << " #" << tmp.number;
}
The constructor, deconstructor, and assignment operator for PriorityQueue:
PriorityQueue::PriorityQueue()
{
std::cout << "\nConstructor called." << endl;
items.elements = new ItemType[maxItems];
length = 0;
}
PriorityQueue::~PriorityQueue()
{
std::cout << "\nDeconstructor called." << endl;
delete[] items.elements;
}
PriorityQueue PriorityQueue::operator=(const PriorityQueue &originalPQ)
{
//This function is started after the return value, the right operand, has been deconstructed.
std::cout << "\nAssignment called." << endl;
for (int i = 0; i < maxItems; i++)
items.elements[i] = originalPQ.items.elements[i];
return *this;
}
It is a little hard to tell exactly what the problem is without looking at how you are returning the PriorityQueue from your FindThroughPaths method, but it is likely that the problem is that you are missing a copy constructor in the PriorityQueue class.
PriorityQueue::PriorityQueue(const PriorityQueue &other)
{
std::cout << "\nCopy constructor was called" << endl;
// there are better ways to implement this, but I think this will correctly
// defer to the assignment operator you wrote
*this = other;
}
When you return an object from a method, the copy constructor is invoked to build the object that will be returned. If you have not implemented a copy constructor, then a default implementation is used, and that default will not be sufficient in your case.
The destructor will still be called to destroy the PriorityQueue object that is local to the FindThroughPaths method.
You might find this other question about returning an object from a method to be helpful.

Understanding the issues of bit copying [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am trying to understand the following code:
blueberry bitCopy(blueberry a) {
cout << "bitCopy " << blueberry::blQuantity << endl;
return a;
}
void howMany() {
cout << blueberry::blQuantity << endl;
}
int main() {
blueberry firstBl;
howMany();
bitCopy(firstBl);
howMany();
}
class blueberry:
#ifndef header_h
#define header_h
#pragma once
#include <string>
#include <iostream>
using namespace std;
class blueberry {
private:
static int blQuantity;
public:
blueberry();
~blueberry() {
blQuantity--;
}
friend blueberry bitCopy(blueberry a);
friend void howMany();
};
#endif
int blueberry::blQuantity = 0;
blueberry::blueberry() {
blQuantity++;
};
class blueberry is just some class that has a static int value blQuantity that increments in the constructor each time an object is created, and decrements in the destructor each time an object goes out of scope.
The read out from this program is:
1
bitCopy 1
-1
I was expecting 0 at the end rather than -1. Can someone explain this please?
PLEASE do not tell me I require a copy constructor. I am not trying to fix this code so that the object count works. I am instead trying to understand how this works and why the blQuantity is not the value I expect.
class blueberry is just some class that has a static int value blQuantity that increments in the constructor each time an object is created, and decrements in the destructor each time an object goes out of scope.
Are you sure that's each and every time one is created? I think there is something you've missed.
blueberry bitCopy(blueberry a)
That's pass-by-value; i.e., blueberry a here is a copy of what was submitted to bitCopy(). That invokes blueberry's copy constructor, which you have not defined. The compiler thus creates a simple one for you, which copies over any member values from the original object -- but it does NOT increment anything. If you want that, you'll have to define:
blueberry::blueberry (const blueberry&) // copy constructor
blueberry& operator= (const blueberry&) // copy assignment operator
You may also want a move constructor and move assignment operator -- see that wikipedia article about the "rule of three (or five)"
I linked in the above paragraph.
The reason blQuantity is -1 at the end is because there are actually two copies made with bitCopy(), one for the parameter and one for the return value. If you change it to:
blueberry bitCopy (blueberry &a)
I.e., using pass-by-reference, there will only be one copy and blQuantity will be 0 afterward. If you then make the return value void, there will be no copies made and blQuantity should be 1.
Here's a demonstration of the roles of the copy constructor and operator= (copy assignment operator):
#include <iostream>
#include <string>
using namespace std;
class A {
public:
string x;
A (string s) : x(s) {
cout << "A con " << "(" << x << ")\n";
}
A (const A& other) : x(other.x) {
x.append("-copy");
cout << "A copy " << "(" << x << ")\n";
}
A& operator= (const A& other) {
x = other.x;
x.append("[=]");
cout << "A assign " << "(" << x << ")\n";
return *this;
}
~A () { cerr << x << " A bye!\n"; }
};
A test (A a) {
return a;
}
int main (void) {
A a("#1");
cout << "test()\n";
A b = test(a);
cout << "Copy assign:\n";
b = a;
cout << "Exiting...\n";
return 0;
}
I'll step through the output from this:
A con (#1)
test()
A copy (#1-copy)
A copy (#1-copy-copy)
#1-copy A bye!
The first line is from A a("#1"). The last three lines are a result of A b = test(a). The first one is copying in the parameter, A test (test a). The second is the creation of the return value, which is a copy of the parameter, so the tag on the object is now #1-copy-copy. That initializes b in main(). When test() exits, the parameter object is destroyed, #1-copy A bye!.
Copy assign:
A assign (#1[=])
This is from b = a in main(). Notice that the previous version of b is not destroyed. This is because copy assignment is meant to turn one object into a copy of another; neither object is destroyed, but the contents of the target object is presumably changed, hence b's tag is now #1[=]. So predictably:
Exiting...
#1[=] A bye!
#1 A bye!
When the program ends, a and b are destroyed.
If you change the signature of test() to:
A& test (A &a)
You'll get this output:
A con (#1)
test()
A copy (#1-copy)
Copy assign:
A assign (#1[=])
Exiting...
#1[=] A bye!
#1 A bye!
Only two objects are ever created, a via the constructor and b via the copy con; both of them are not destroyed until the end. If you then do not use the return value of test(), only one object is ever created.

C++ Class Constructor / Destructor

I have a below code. Every time Constructor is called, I increase a counter and the counter is decreased every time Destructor is called. After instantiating three class objects, I tried printing out the counter value. Then I tried printing out the counter value again after deleting one of the objects. The expected values were 4 and 3, but instead I get 2 and 1.
I actually tried printing out something within the Constructor and Destructor to observe how many times they were actually called, but surprisingly Destructor was called several times in addition to the time when I called "delete object". Is it because the Destructor is called automatically? If so, is there any way to turn the feature off to test my code?
** The code originally has Add and Mult functions in the class, but I omitted here because the details of the functions seem irrelevant here.
#include <iostream>
using namespace std;
class Complex{
private:
double x, y;
static int count;
Complex Add(Complex como)
{
Complex t;
t.x=x+como.x;
t.y=y+como.y;
return t;
}
Complex Mul(Complex como)
{
Complex t;
t.x=(x*como.x)-(y*como.y);
t.y=(y*como.x)+(x*como.y);
return t;
}
public:
Complex(double a=0, double b=0) : x(a), y(b) {count++;}
~Complex() {count--;}
void Print() {cout << "(" << x << ", " << y << ")" << endl;}
static int GetCount() {return count;}
};
int Complex::count=0;
int main()
{
Complex com1(1.0, 2.0), com2(3.0, 4.0);
Complex com3;
com1.Print(); cout << endl;
com2.Print(); cout << endl;
com3 = com1.Add(com2); com3.Print(); cout << endl;
Complex *pcom4 = new Complex;
*pcom4 = com1.Mul(com2); pcom4->Print(); cout << endl;
cout << "#complex numbers = " << com1.GetCount() << endl;
delete pcom4;
cout << "#complex numbers = " << com1.GetCount() << endl;
return 0;
}
In C++ you can construct objects in three ways:
using the "constructor"
using the "copy constructor"
using the "move constructor"
If don't define them the compiler will automatically write the code for you (unless you stop it from doing that explicitly).
Your method Mul and Add are accepting the other complex number by value and this means that a copy constructor call will be used to copy the argument of the call.
The automatic synthesized copy constructor doesn't increment the counter.
Your methods are taking Complex objects as parameters (not references to existing objects), so new objects are being created for each call and are destroyed at the end of the call.

Copy constructor not called?

As far as I know you call the copy constructor in the following cases:
1 When instantiating one object and initializing it with values from another object
2 When passing an object by value.
3 When an object is returned from a function by value.
I decided to put this to the test and I made this small program testing this (with messages each time a constructor is called. It seems to work for the first two cases, but not for the third one. I want to find out my mistake. Ideas are welcomed.
#include <iostream>
using namespace std;
class Circle{
private:
double* data;
public:
Circle();
Circle(double* set);
Circle(const Circle& tt1);
~Circle();
Circle& operator=(const Circle& tt1);
};
Circle :: Circle()
{
cout << "Default constructor called" << endl;
data = NULL;
}
Circle :: Circle(double* set)
{
cout << "Set up constructor called" << endl;
data = new double[3];
copy(set, set+3, data);
}
Circle :: Circle(const Circle& tt1)
{
cout << "Copy constructor called" << endl;
data = new double[3];
copy(tt1.data, tt1.data+3, this->data);
}
Circle :: ~Circle()
{
cout << "Destructor called!" << endl;
delete[] data;
}
Circle& Circle :: operator=(const Circle& tt1)
{
cout << "Overloaded = called" << endl;
if(this != &tt1)
{
delete[] this->data;
this->data = new double[3];
copy(tt1.data, tt1.data+3, this->data);
}
return *this;
}
void test2(Circle a)
{
}
Circle test3()
{
double arr [] = { 3, 5, 8, 2};
Circle asd(arr);
cout<< "end of test 3 function" << endl;
return asd;
}
int main()
{
cout <<"-------------Test for initialization" << endl;
double arr [] = { 16, 2, 7};
Circle z(arr);
Circle y = z;
cout << "-------------Test for pass by value" << endl;
test2(z);
cout <<"------------- Test for return value-------"<<endl;
Circle work = test3();
cout<< "-----------Relese allocated data" << endl;
return 0;
}
Because of Return Value Optimization the 3rd test case's copy constructor call is optimized away by the compiler.
In virtually all cases, the compiler is not allowed to change the meaning of your code. It can (and will when optimising) change your code dramatically from what you wrote into something more optimal whilst never changing the observable behaviour of your code.
This is why when debugging you'll see many confusing things as the generated code does something totally different from what you wrote whilst keeping the observable state intact. This actually makes writing debuggers hard - if for instance you want to examine the value of a variable whilst debugging, the compiler may've decided that the variable didn't even need to exist and so in that case what should the debugger show?
In a very small number of cases the compiler is allowed to change the meaning of your code. The RVO and NRVO [same link as above] are two examples of these - the compiler is allowed to elide the copy constructor in these limited cases - which is what you are seeing. The compiler should still check that your copy constructor exists and is accessible - for instance it isn't private, deleted or impossible to generate - but it can then not use it.
For this reason Copy Constructors [and by inference destructors] should just do the normal thing - as if they're elided you'll get observably different behaviour.

returning C++ stack variable

In this example, why is it ok to return a stack variable? When t() returns, why is it not returning garbage, since the stack pointer has been incremented?
#include << string >>
#include << vector >>
#include << iostream >>
using namespace std;
class X{
public:
X() { cout << "constructor" << endl; }
~X() { cout << "destructor" << endl; }
};
vector <X> t()
{
cout << "t() start" << endl;
vector<X> my_x;
int i = 0;
printf("t: %x %x %x\n", t, &my_x, &i);
my\_x.push\_back(X()); my\_x.push\_back(X()); my\_x.push\_back(X());
cout << "t() done" << endl;
return my_x;
}
int main()
{
cout << "main start" << endl;
vector <X> g = t();
printf("main: %x\n", &g);
return 0;
}
output:
./a.out
main start
t() start
t: 8048984 bfeb66d0 bfeb667c
constructor
destructor
constructor
destructor
destructor
constructor
destructor
destructor
destructor
t() done
main: bfeb66d0
destructor
destructor
destructor
Basically when you return the stack variable my_x you would be calling the copy constructor to create a new copy of the variable. This is not true, in this case, thanks to the all mighty compiler.
The compiler uses a trick known as return by value optimization by making the variable my_x really being constructed in the place of memory assigned for g on the main method. This is why you see the same address bfeb66d0 being printed. This avoids memory allocation and copy construction.
Sometimes this is not at all possible due to the complexity of the code and then the compiler resets to the default behavior, creating a copy of the object.
Because parameters are passed by value. A copy is made. So what is being returned is not the value on the stack, but a copy of it.
Well a copy is returned, the only construct you can not return a copy of it is a static array. So you can not say this...
int[] retArray()
{
int arr[101];
return arr;
}
The compiler is optimized to handle returning "stack variables" without calling the copy constructor. The only thing you need to know about is that that memory allocation is in scope of both the function that allocated it on the stack and the function that the object is returned to.
It does NOT call the copy constructor nor does it allocate it twice.
There may be some special cases and of course it depends on the compiler -- for example, primitives may be copied -- but in general, objects allocated on the stack, don't get copied when being returned.
Example:
struct Test {
};
Test getTest() {
Test t;
std::cout << &t << std::endl; // 0xbfeea75f
return t;
}
int main(int argc, char *argv[])
{
Test t = getTest();
std::cout << &t << std::endl; // also 0xbfeea75f
}