Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Destructor called when objects are passed by value

Tags:

c++

Even though objects are passed to functions by means of the normal call-by-value parameter passing mechanism, which, in theory, protects and insulates the calling argument, it is still possible for a side effect to occur that may affect, or even damage, the object used as an argument. For example, if an object used as an argument allocates memory and frees that memory when it is destroyed, then its local copy inside the function will free the same memory when its destructor is called. This will leave the original object damaged and effectively useless.

This is written in C++: The Complete Reference

In this program here

#include<iostream>

using namespace std;

class Sample
{         
 public:
         int *ptr;
         Sample(int i)
         {
         ptr = new int(i);
         }
         ~Sample()
         {
         cout<<"destroyed";
         delete ptr;
         }
         void PrintVal()
         {
         cout << "The value is " << *ptr;
         }
 };
 void SomeFunc(Sample x)
{
 cout << "Say i am in someFunc " << endl;
}
 int main()
{
 Sample s1= 10;
SomeFunc(s1);
 s1.PrintVal();
}

It generates a runtime error as the object s1 is destroyed when it returns from the object. I couldnt figure out why this might happen, since a copy should have been made. I thought maybe it was because there was no copy constructor present in the class defination. But i was surprised to find that if use this function declaration

 void SomeFunc(Sample &x)
{
 cout << "Say i am in someFunc " << endl;
}

In this declaration no error occurs. Shouldnt the error occur here as well because it is referenced? Can anyone explain what happens in both cases.

like image 792
Shaurya Chaudhuri Avatar asked Sep 22 '14 07:09

Shaurya Chaudhuri


1 Answers

This is indeed because you didn't provide a copy constructor. Thus the compiler will generate one for you, which does trivial copy. And that's the trivial copy of the pointer that's problematic here.

For the following declaration

void SomeFunc(Sample x);

There will be indeed a copy when you pass s1 to the function, but this copy will have a copy of the pointer, that is, the two object will point to the same int.

Then, when exiting the function, the copy will be destroyed and will delete that pointer, leaving the original object in the calling code with a pointer just deleted (remember, they point to the same thing).

Then, for the following declaration

void SomeFunc(Sample &x);

you don't have any copy, thus the problem doesn't show up. Indeed, passing by reference means that inside the function, the Sample object you're manipulating is exactly the same as the one you passed to the function, and won't be destroyed when the function exits.

like image 74
JBL Avatar answered Oct 21 '22 18:10

JBL