Reputation: 349
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
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
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