user2445455
user2445455

Reputation: 349

Does a destructor call itself when an object passed as a parameter goes out of scope?

I am using a static variable to keep track of the number of instances of an object. I am getting some unpredictable behavior with the following code:

#include <iostream>
using namespace std;

class comp{
private:
 int a;
 int b;

 public:
  friend comp &operator+(comp, comp);
   static int c;
   comp(int, int);
   comp();
   ~comp();
   int getA();
   int getB();
   void print() const;
};

int comp::c = 0;

comp::~comp() {

    c--;
    cout << "destroying comp of " << a << ", " << b << ", count after decrement is  " << c << endl;
    }


comp &operator+(comp A, comp B){
  comp C = comp(A.a + B.a, A.b + B.b);
  cout << "in +, count is " << comp::c << endl;
  return C;
}

comp::comp(int A, int B){
  a = A;
  b = B;
  c++;
}

comp::comp(){
  a = 0; b = 0; c++;
}

int comp::getA(){
  return a;
}

int comp::getB(){
  return b;
}

void comp::print() const{
  cout << a << ", " << b << endl;
}

int main()
{
    cout << comp::c << endl;
    comp A = comp(3,4);
    cout << comp::c << endl;
    comp B = comp(4,5);
    cout << comp::c << endl;
    A + B;
    A.print();
    B.print();
    cout << "About to exit main, c is: " << comp::c << endl;
    return 0;
}

Output is this:

0
1
2
in +, count is 3
destroying comp of 7, 9, count after decrement is  2
destroying comp of 3, 4, count after decrement is  1
destroying comp of 4, 5, count after decrement is  0
3, 4
4, 5
About to exit main, c is: 0
destroying comp of 4, 5, count after decrement is  -1
destroying comp of 3, 4, count after decrement is  -2

This behavior is being caused by the line

 A + B;

My best guess as to what is happening is that when the objects are passed in as parameters to a function, the constructor is not being called (so c is not being incremented), but when the function goes out of scope, the destructor is called. This leads to a net loss in count.

However, the overloaded operator+ passed variables by references. Wouldn't this prevent the parameters from going out of scope and the destructor being called?

The output is the same regardless of whether the overloaded + operator is declared as:

friend comp &operator+(comp, comp);

or

friend comp operator+(comp, comp);

This leads me confused as to why and how the destructor is being called.

One last question: is it good practice, when using overloaded operators, to pass by reference rather than by value? If so, why?

Thanks!

EDIT: It appears as if I was confusing the syntax a bit. I thought that

friend comp &operator+(comp, comp);

was passing the parameters by reference instead of

friend comp operator+(comp&, comp&);

Excuse my noobish question, but could someone explain what the "&" operator does before a function name? If I understand correctly, "&" is the reference operator and gives the address given a variable. However, if one would want to return a reference, the "*" operator would be appropriate. For instance:

int *a()

The above function signature returns a memory address that points to an int.

int &a()

What would that function signature return?

Upvotes: 2

Views: 1246

Answers (2)

OlivierH
OlivierH

Reputation: 347

Your problem is that when you get objects as parameters, you make a copy of them. And that's that copy which will be destructed at the end of the scope. In order to avoid that, you should pass them by reference:

comp operator+(comp& a, comp& b);

The & in the return type is of the return value, i.e. C in your code. And this is bad, because you send a reference to a variable created locally, which will be destroyed at the end of the scope.

Upvotes: 1

Tomek
Tomek

Reputation: 4659

You are not accounting for objects created by default, compiler generated copy constructor. Define one, count the objects created there and the math will work out.

Upvotes: 4

Related Questions