views:

213

answers:

4

The following code gives a different number of destructors when compiled on GCC and vc9. AFAIK when run on vc9 i get 5 destructors showing, which I understand. The + overloaded operator is called, and two object are created, when returned a temporary object is created. This makes destruction of 3 objects possible. When the overloaded = operator is called, one object is created and again a temporary one when returned. This sums it up to five destructs, not counting the three objects created at the start of main.

But when I compile on GCC I get 3.

Which leads me to guess that there isn't a temporary object created when the function is terminated and returned ? or a question about different behavior between compilers. I simply do not know, and some clarification would be nice.

#include <iostream>
using namespace std;

class planetCord {
    double x, y, z;
public:
    planetCord() { x = y = z = 0; }
    planetCord(double j, double i, double k) { x = j; y = i; z = k; }    
    ~planetCord() { cout << "destructing\n"; }
    planetCord operator+(planetCord obj);
    planetCord operator=(planetCord obj);
    void show();
};

planetCord planetCord::operator +(planetCord obj) {
    planetCord temp;
    temp.x = x + obj.x;
    temp.y = y + obj.y;
    temp.z = z + obj.z;
    return temp;
}

planetCord planetCord::operator =(planetCord obj) {
    x = obj.x;
    y = obj.y;
    z = obj.z;
    return *this;
}

void planetCord::show() {
    cout << "x cordinates: " << x << "\n";
    cout << "y cordinates: " << y << "\n";
    cout << "z cordinates: " << z << "\n\n";
}

int main() {
    planetCord jupiter(10, 20, 30);
    planetCord saturn(50, 100, 200);
    planetCord somewhereDark;

    jupiter.show();
    saturn.show();
    somewhereDark.show();
    somewhereDark = jupiter + saturn;  
    jupiter.show();
    saturn.show();
    somewhereDark.show();
    return 0;
}
+1  A: 

A permissible but not mandatory optimization for a C++ compiler is to turn the tight sequence:

ctor for new temporary object X
copy ctor from X to other object Y
dtor for X

into just performing the ctor directly on Y. A really good C++ optimizer can do that across a function clal (i.e. when X is the return value for a function). Looks like gcc is optimizing better. Does the result change as you play with optimization options for the two compilers?

Alex Martelli
I couldn't get the results to change, except when I set visual studio to release mode. Tried to set different optimizations and play with the settings, but it stayed the same.
Tecurik
+3  A: 

GCC is implementing the "return value optimization" to skip temporaries. Set VC9 to Release mode and it'll probably do the same.

If GCC is really good, it is seeing that temp inside operator+ will be default-initialized, just like somewhereDark, and can just use a reference to somewhereDark directly if it tries to inline the function. Or it is seeing that the pass-by-value is useless and can instead pass-by-reference.

rlbond
vc9 produces 4 destructors when set to release mode. I tried to play with different optimizations on the project, but couldn't produce the same result.
Tecurik
Rick
A: 

Actually, in GCC, temporaries ARE being made. They are:

  • In operator+.
  • Returned by operator+.
  • Returned by operator=.

In MSVC (I think; can't test), temporaries are being made as well. However, some are not being optimized away like GCC does. They are:

  • As a parameter to operator+.
  • In operator+.
  • Returned by operator+.
  • As a parameter to operator=.
  • Returned by operator=.

Ironically I think MSVC is in the right here, because I'm not sure if GCC's behaviour is standard.

To make them both behave the same, use const references instead of passing the object by value.

strager
That's a brave claim to make about GCC not being standard. What optimization do you think causes GCC not to be standards conform-ant?
Martin York
@York, I don't know the standards near well enough to say. I just /suspect/ it may not be what the standards say it should (could?) be.
strager
@Stranger: If you don't know the standard well enough to say, then you definitely don't know enough to make that claim. I suspect that GCC is compliant.
Martin York
I said "I think" and "I'm not sure." I thought that was enough disclaimer. =X
strager
+2  A: 

There are a number of of things wrong with your code. Can I suggest you investigate two concepts - consts and references. If your C++ text book doesn't cover these, get a new text book - I strongly recommend Accelerated C++ by Koenig & Moo.

anon
Already planned to read it after I finish the one I am reading now. Heard my current textbook introduced bad practices, so I was recommended the one you mentioned.
Tecurik
If your current inspired the above code don't finish it. It's not only bad, it's plainly wrong.
sbi