Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. return value - destructor call?

return value - destructor call?

Scheduled Pinned Locked Moved C / C++ / MFC
questionperformancehelp
11 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Z Offline
    Z Offline
    zqueezy
    wrote on last edited by
    #1

    hey folks, I wrote a little wrapper for the gsl-library and had to face a problem I never had expected (and never noticed before). It's a simple class-question... So first the code: // Class Header class myClass { public: myClass(); ~myClass(); myClass Testfunction(); int val; }; // Class Implementation myClass::myClass() { val=0; } myClass::~myClass() { int t = 0; int h = t; this->val = val; cout << "Destructor called\n"; } myClass myClass::Testfunction() { myClass newClass; newClass.val = 7; return newClass; } // Main int main() { myClass A; myClass B; cout << "Calling test function\n"; B = A.Testfunction(); cout << "Print out value:\n"; cout << B.val << "\n"; cout << "Waiting for user...\n"; cin.get(); } Allright... actually there shouldn't be any destructor called BEFORE the cin.get(). The output is: Calling test function Destructor called // WHY??? Destructor called // WHY??? Print out value: 7 Waiting for user... The Destructor is somehow called for the return value and I don't know why... And even if I get an explanation... is there a way of not calling the destructor here? (Compiler setting???) because I actually free some memory in my prog in the destructor and when the memory is freed I never get it back... :( any idea?? thx in advance zqueezy

    I N T Z 5 Replies Last reply
    0
    • Z zqueezy

      hey folks, I wrote a little wrapper for the gsl-library and had to face a problem I never had expected (and never noticed before). It's a simple class-question... So first the code: // Class Header class myClass { public: myClass(); ~myClass(); myClass Testfunction(); int val; }; // Class Implementation myClass::myClass() { val=0; } myClass::~myClass() { int t = 0; int h = t; this->val = val; cout << "Destructor called\n"; } myClass myClass::Testfunction() { myClass newClass; newClass.val = 7; return newClass; } // Main int main() { myClass A; myClass B; cout << "Calling test function\n"; B = A.Testfunction(); cout << "Print out value:\n"; cout << B.val << "\n"; cout << "Waiting for user...\n"; cin.get(); } Allright... actually there shouldn't be any destructor called BEFORE the cin.get(). The output is: Calling test function Destructor called // WHY??? Destructor called // WHY??? Print out value: 7 Waiting for user... The Destructor is somehow called for the return value and I don't know why... And even if I get an explanation... is there a way of not calling the destructor here? (Compiler setting???) because I actually free some memory in my prog in the destructor and when the memory is freed I never get it back... :( any idea?? thx in advance zqueezy

      I Offline
      I Offline
      Iain Clarke Warrior Programmer
      wrote on last edited by
      #2

      The Testfunction returns myClass also. newclass doesn't exist past the end of testfunction, so the function returns a copy of it... Temporary copy needs constructing, and (drumroll) destructing. Try adding another member to myClass, and a constructor which assigns a random value to it. Then also spit it out in the destructor. See how its actually different myClass instances getting killed. As to the avoidance? That all depends on what you were really trying to do. What you have posted is a very artificial example to show the "double" destructing, it doesn't show what you were trying to do when you ran into this issue. And just in case this is homework, as least I've only done 50% of your work. Iain.

      Z 1 Reply Last reply
      0
      • Z zqueezy

        hey folks, I wrote a little wrapper for the gsl-library and had to face a problem I never had expected (and never noticed before). It's a simple class-question... So first the code: // Class Header class myClass { public: myClass(); ~myClass(); myClass Testfunction(); int val; }; // Class Implementation myClass::myClass() { val=0; } myClass::~myClass() { int t = 0; int h = t; this->val = val; cout << "Destructor called\n"; } myClass myClass::Testfunction() { myClass newClass; newClass.val = 7; return newClass; } // Main int main() { myClass A; myClass B; cout << "Calling test function\n"; B = A.Testfunction(); cout << "Print out value:\n"; cout << B.val << "\n"; cout << "Waiting for user...\n"; cin.get(); } Allright... actually there shouldn't be any destructor called BEFORE the cin.get(). The output is: Calling test function Destructor called // WHY??? Destructor called // WHY??? Print out value: 7 Waiting for user... The Destructor is somehow called for the return value and I don't know why... And even if I get an explanation... is there a way of not calling the destructor here? (Compiler setting???) because I actually free some memory in my prog in the destructor and when the memory is freed I never get it back... :( any idea?? thx in advance zqueezy

        I Offline
        I Offline
        Iain Clarke Warrior Programmer
        wrote on last edited by
        #3

        Ach, I'm weak. Below is a copy of a =operator function, where you can see the return type is a reference to object, rather than the object. This allows you to dasiy chain loads of =s together.

        RgbQuad &operator=(RgbQuad &r)
        {
        	rgbRed	= r.rgbRed;
        	rgbGreen= r.rgbGreen;
        	rgbBlue	= r.rgbBlue;
        	return	\*this;
        };
        

        I hope that steers you in the right direction. Iain.

        1 Reply Last reply
        0
        • Z zqueezy

          hey folks, I wrote a little wrapper for the gsl-library and had to face a problem I never had expected (and never noticed before). It's a simple class-question... So first the code: // Class Header class myClass { public: myClass(); ~myClass(); myClass Testfunction(); int val; }; // Class Implementation myClass::myClass() { val=0; } myClass::~myClass() { int t = 0; int h = t; this->val = val; cout << "Destructor called\n"; } myClass myClass::Testfunction() { myClass newClass; newClass.val = 7; return newClass; } // Main int main() { myClass A; myClass B; cout << "Calling test function\n"; B = A.Testfunction(); cout << "Print out value:\n"; cout << B.val << "\n"; cout << "Waiting for user...\n"; cin.get(); } Allright... actually there shouldn't be any destructor called BEFORE the cin.get(). The output is: Calling test function Destructor called // WHY??? Destructor called // WHY??? Print out value: 7 Waiting for user... The Destructor is somehow called for the return value and I don't know why... And even if I get an explanation... is there a way of not calling the destructor here? (Compiler setting???) because I actually free some memory in my prog in the destructor and when the memory is freed I never get it back... :( any idea?? thx in advance zqueezy

          N Offline
          N Offline
          Nemanja Trifunovic
          wrote on last edited by
          #4

          zqueezy wrote:

          Allright... actually there shouldn't be any destructor called BEFORE the cin.get().

          Of course it should.

          zqueezy wrote:

          The Destructor is somehow called for the return value and I don't know why...

          Because newClass went out of scope, and the destructor must be called in that case.

          zqueezy wrote:

          is there a way of not calling the destructor here?

          Rewrite the function like this:

          void myClass::Testfunction(myClass& obj)
          {
          obj.val = 7;
          }

          Create the object before calling it, and pass it as the argument.


          Programming Blog utf8-cpp

          Z 1 Reply Last reply
          0
          • Z zqueezy

            hey folks, I wrote a little wrapper for the gsl-library and had to face a problem I never had expected (and never noticed before). It's a simple class-question... So first the code: // Class Header class myClass { public: myClass(); ~myClass(); myClass Testfunction(); int val; }; // Class Implementation myClass::myClass() { val=0; } myClass::~myClass() { int t = 0; int h = t; this->val = val; cout << "Destructor called\n"; } myClass myClass::Testfunction() { myClass newClass; newClass.val = 7; return newClass; } // Main int main() { myClass A; myClass B; cout << "Calling test function\n"; B = A.Testfunction(); cout << "Print out value:\n"; cout << B.val << "\n"; cout << "Waiting for user...\n"; cin.get(); } Allright... actually there shouldn't be any destructor called BEFORE the cin.get(). The output is: Calling test function Destructor called // WHY??? Destructor called // WHY??? Print out value: 7 Waiting for user... The Destructor is somehow called for the return value and I don't know why... And even if I get an explanation... is there a way of not calling the destructor here? (Compiler setting???) because I actually free some memory in my prog in the destructor and when the memory is freed I never get it back... :( any idea?? thx in advance zqueezy

            T Offline
            T Offline
            Taka Muraoka
            wrote on last edited by
            #5

            zqueezy wrote:

            The Destructor is somehow called for the return value and I don't know why...

            The newClass object in your test function is created on the stack and so cannot be used by anyone once the function exits. So the compiler has to copy it into your B variable, then destroy the newClass object. I think you're getting two calls to the destructor because the compiler is copying the newClass object into a temporary "return value" object and then copying this one into the B variable. Google for something called "return value optimization" for info on how to get rid of this.

            zqueezy wrote:

            is there a way of not calling the destructor here?

            Nope. The newClass object *must* be destroyed (since it's on the stack).

            zqueezy wrote:

            because I actually free some memory in my prog in the destructor

            This is usually not the best way of designing things but if you absolutely have to do it like this, allocate the newClass object from the heap (using "new") and return a pointer to that.


            I enjoy occasionally wandering around randomly, and often find that when I do so, I get to where I wanted to be [^]. Awasu 2.3 [^]: A free RSS/Atom feed reader with support for Code Project. 50% discount on the paid editions for CP members!

            Z 1 Reply Last reply
            0
            • I Iain Clarke Warrior Programmer

              The Testfunction returns myClass also. newclass doesn't exist past the end of testfunction, so the function returns a copy of it... Temporary copy needs constructing, and (drumroll) destructing. Try adding another member to myClass, and a constructor which assigns a random value to it. Then also spit it out in the destructor. See how its actually different myClass instances getting killed. As to the avoidance? That all depends on what you were really trying to do. What you have posted is a very artificial example to show the "double" destructing, it doesn't show what you were trying to do when you ran into this issue. And just in case this is homework, as least I've only done 50% of your work. Iain.

              Z Offline
              Z Offline
              zqueezy
              wrote on last edited by
              #6

              well, no it's no homework. I'm well aware of the fact that the copy-call is run for the object that went out of scope... To make my example less artificial: In gsl a matrix need allocation of memory (alloc) and freeing the memory, of course. I tried to write a matrix-class which does the allocation in the constructor and which does the freeing in the destructor. Now I wrote an operator function for the multiplication: CMatrix CMatrix::operator *(const CMatrix& factorMatrix); when I try to return the resulting matrix the destructor is called and the memory freed thus the matrix deleted and cannot be assigned with any operation like the operator=... better? zqueezy

              I 1 Reply Last reply
              0
              • T Taka Muraoka

                zqueezy wrote:

                The Destructor is somehow called for the return value and I don't know why...

                The newClass object in your test function is created on the stack and so cannot be used by anyone once the function exits. So the compiler has to copy it into your B variable, then destroy the newClass object. I think you're getting two calls to the destructor because the compiler is copying the newClass object into a temporary "return value" object and then copying this one into the B variable. Google for something called "return value optimization" for info on how to get rid of this.

                zqueezy wrote:

                is there a way of not calling the destructor here?

                Nope. The newClass object *must* be destroyed (since it's on the stack).

                zqueezy wrote:

                because I actually free some memory in my prog in the destructor

                This is usually not the best way of designing things but if you absolutely have to do it like this, allocate the newClass object from the heap (using "new") and return a pointer to that.


                I enjoy occasionally wandering around randomly, and often find that when I do so, I get to where I wanted to be [^]. Awasu 2.3 [^]: A free RSS/Atom feed reader with support for Code Project. 50% discount on the paid editions for CP members!

                Z Offline
                Z Offline
                zqueezy
                wrote on last edited by
                #7

                I didn't want to do a heap allocation... for the reason of the easy-user interface (see my first reply) but perhaps... that's the only possibility. thanx for all your help

                1 Reply Last reply
                0
                • N Nemanja Trifunovic

                  zqueezy wrote:

                  Allright... actually there shouldn't be any destructor called BEFORE the cin.get().

                  Of course it should.

                  zqueezy wrote:

                  The Destructor is somehow called for the return value and I don't know why...

                  Because newClass went out of scope, and the destructor must be called in that case.

                  zqueezy wrote:

                  is there a way of not calling the destructor here?

                  Rewrite the function like this:

                  void myClass::Testfunction(myClass& obj)
                  {
                  obj.val = 7;
                  }

                  Create the object before calling it, and pass it as the argument.


                  Programming Blog utf8-cpp

                  Z Offline
                  Z Offline
                  zqueezy
                  wrote on last edited by
                  #8

                  when I do the whole thing as reference... why is the destructor called anyways... isn't the reference just an address?

                  N 1 Reply Last reply
                  0
                  • Z zqueezy

                    when I do the whole thing as reference... why is the destructor called anyways... isn't the reference just an address?

                    N Offline
                    N Offline
                    Nemanja Trifunovic
                    wrote on last edited by
                    #9

                    zqueezy wrote:

                    when I do the whole thing as reference... why is the destructor called anyways

                    No, it is not.


                    Programming Blog utf8-cpp

                    1 Reply Last reply
                    0
                    • Z zqueezy

                      well, no it's no homework. I'm well aware of the fact that the copy-call is run for the object that went out of scope... To make my example less artificial: In gsl a matrix need allocation of memory (alloc) and freeing the memory, of course. I tried to write a matrix-class which does the allocation in the constructor and which does the freeing in the destructor. Now I wrote an operator function for the multiplication: CMatrix CMatrix::operator *(const CMatrix& factorMatrix); when I try to return the resulting matrix the destructor is called and the memory freed thus the matrix deleted and cannot be assigned with any operation like the operator=... better? zqueezy

                      I Offline
                      I Offline
                      Iain Clarke Warrior Programmer
                      wrote on last edited by
                      #10

                      The "extra" destructor you're getting is because you're being nice and elegant and writing a * operator, which (quite correctly) returns an instance (albeit a temporary one) on CMatrix. If the constructor / destructor is "expensive", then you're going to have to do it a different way.

                      class CMatrix
                      {
                      public:
                      ....
                      BOOL Multiply (CMatrix const &lhs, CMatrix const &rhs)
                      {
                      if (!ValidToDoThisMaths (lhs, rhs))
                      return FALSE;
                      // Do gnarly maths here to multiply lhs & rhs and keep the results in this
                      ....
                      return TRUE;
                      }
                      ....
                      };

                      void main ()
                      {
                      CMatrix A,B,C;

                      A.Create (blah);   // <-- however you make them have something interesting in them
                      B.Set (blah);
                      
                      // we'd like   C = A \* B;   but that would mean expensive operations with temp matrix
                      C.Multiply (A,B);
                      
                      C.DoStuff ();
                      

                      }

                      Its less elegant, but it would solve your problem. It would also lose the ability to do:

                      D = A * B * C

                      but frankly, matrices are enough of a pain to work with [ (n x m) * (m x n) etc ] that that's probably not a huge loss. I hope that helped, Iain.

                      1 Reply Last reply
                      0
                      • Z zqueezy

                        hey folks, I wrote a little wrapper for the gsl-library and had to face a problem I never had expected (and never noticed before). It's a simple class-question... So first the code: // Class Header class myClass { public: myClass(); ~myClass(); myClass Testfunction(); int val; }; // Class Implementation myClass::myClass() { val=0; } myClass::~myClass() { int t = 0; int h = t; this->val = val; cout << "Destructor called\n"; } myClass myClass::Testfunction() { myClass newClass; newClass.val = 7; return newClass; } // Main int main() { myClass A; myClass B; cout << "Calling test function\n"; B = A.Testfunction(); cout << "Print out value:\n"; cout << B.val << "\n"; cout << "Waiting for user...\n"; cin.get(); } Allright... actually there shouldn't be any destructor called BEFORE the cin.get(). The output is: Calling test function Destructor called // WHY??? Destructor called // WHY??? Print out value: 7 Waiting for user... The Destructor is somehow called for the return value and I don't know why... And even if I get an explanation... is there a way of not calling the destructor here? (Compiler setting???) because I actually free some memory in my prog in the destructor and when the memory is freed I never get it back... :( any idea?? thx in advance zqueezy

                        Z Offline
                        Z Offline
                        zqueezy
                        wrote on last edited by
                        #11

                        To give my end-solution: I didn't know I had to create a Copy-Constructor for my class, you need a copy-constructor for classes that allocate memory dynamically...

                        1 Reply Last reply
                        0
                        Reply
                        • Reply as topic
                        Log in to reply
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes


                        • Login

                        • Don't have an account? Register

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • World
                        • Users
                        • Groups