2

I am very new to C++ and I don't understand why the copy constructor was called in the following code:

 #include <iostream> 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; // allocate memory for the pointer; 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) { cout << "Length of line : " << obj.getLength() <<endl; } // Main function for the program int main( ) { Line line(10); display(line); return 0; } 

And when it runs:

Normal constructor allocating ptr Copy constructor allocating ptr. Length of line : 10 Freeing memory! Freeing memory! 

Why does it construct an other Line object after the first one with the simple constructor?

Thanks!

3
  • 2
    Read about pass by value, pointer or reference. Commented Aug 31, 2016 at 21:26
  • 1
    @SamVarshavchik: right! it's better to learn C++ first then Java. But in schools they teach only Java because C++ is "too hard". Ok but C++ is useful! Commented Aug 31, 2016 at 21:35
  • Why does this have upvotes... Commented Aug 31, 2016 at 22:33

4 Answers 4

7

because you are passing Line as value

void display(Line obj) { cout << "Length of line : " << obj.getLength() <<endl; } 

You should pass it as constant reference, which is faster (and display shoud be a constant method so constant objects can call it).

void display(const Line &obj) const { cout << "Length of line : " << obj.getLength() <<endl; } 

(provided that you change to int getLength( void ) const;)

And in your case, think of redefining assignment operator

Line &operator=(const Line &other); 

or affecting a line in another will copy pointer data and will crash on your second object deletion since memory will be freed twice.

If you want to make sure that default copy constructor / assignment operator cannot be called, just declare them in your private part:

private: Line &operator=(const Line &other); Line(const Line &other); 

code trying to use them won't compile.

Sign up to request clarification or add additional context in comments.

2 Comments

Please stick to the answer of the question only and remove that part after General advice, because there is no general advice. Whether some data should be allocated on the heap (via new) depends highly on the context and use-case.
Ok, I have added some more relevant info instead about how to forbid copy/assignment. I hope it's OK.
1

Your display function takes a Line by value - meaning the function gets its own copy. If you don't want that, pass by (const) reference or pointer instead.

Comments

1

The answer is here:

void display(Line obj) { ... 

The argument of the function obj is passed by value.

So when the function is called a copy of the argument passed by the caller function is done.

In order to give you a trivial explanation, imagine:

function:main (caller) -> make a copy of line -> call the function display (callee) which is going to use the copy made by caller. 

That policy is used in various case, for example:

  • To be sure that the callee function will does any effect (side-effect) on the variables of the caller.
  • When the callee function will perform a copy of the object, so you can avoid to make a copy inside the body function.

Because passing an argument by value will perform a copy of the argument itself, it is preferable using argument passed by reference.

This is an example:

void display(Line& obj) { ... 

In that case it will not performed a copy of the object but the argument obj will be a reference (like a pointer) to the argument passed by the caller function.

In conclusion, passing by reference allows to callee function side effect, in other words the callee function can modify variables "owned" by caller function.

Comments

1

Copy constructors are called in following cases:

(a) when a function returns an object of that class by value

(b) when the object of that class is passed by value as an argument to a function

(c) when you construct an object based on another object of the same class

(d) When compiler generates a temporary object and is initialized with a class object.

And in your code you are passing the object of that clas by value as an argument to a function Hope this Helps

7 Comments

Besides copy elision applies.
When compiler generates a temporary object does not mean the copy c'tor was called. It is only called if the temporary is initialized with a class object.
Copy constructors are called in following cases: -- Realize that none of those items guarantees a call of the copy constructor.
@PaulMcKenzie but can we rule out that copy con is nt called, even in the above case , the object is passed by value as an argument, Correct me if aim wrong Thanks
@NathanOliver Modified the the answer
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.