Thread: this returned destructor called...

  1. #1
    Normal vector Carlos's Avatar
    Join Date
    Sep 2001
    Location
    Budapest
    Posts
    463

    "*this" returned destructor called...

    Hi!

    While testing a project I noticed a weird behaviour.
    Here is the draft class:
    Code:
    Class MyClass
    {
    public:
    MyClass();
    ~MyClass();
    MyClass self() { return *this; }
    }
    And here comes the problem:

    Code:
    MyClass anObj;
    anObj.self();
    // PROBLEM HERE - after returning from self() function, de destructor of MyClass gets called
    // do something
    If I change the self() to return a reference:
    Code:
    MyClass& self() { return *this; }
    then the destructor isn't called.

    Do you have a good explanation for this one?
    Last edited by Carlos; 09-24-2003 at 06:51 AM.

  2. #2
    Amateur
    Join Date
    Sep 2003
    Posts
    228
    Excuse my rudeness but I don't think it is weird or something. Maybe don't I just understand anything. ^^

    So, I was saying that it is perfectly natural that the destructor is called, I don't know if you have realized that yet but in fact no function really "returns" an object, it's obvious that we could never make the EAX register huge enough to hold so much data.
    Therefore, when we call a function that returns an object, the program actually calls the function with an extra argument, a pointer to a variable that will be initialized by the function. (sorry if I'm wasting your time and if you already knew that)
    So, with that said, it appears clearly that once the object was created by the called-function, it must be deleted by the caller even if it was not used or even assigned to a "visible" variable.

  3. #3
    pronounced 'fib' FillYourBrain's Avatar
    Join Date
    Aug 2002
    Posts
    2,297
    when you return a value like that, you create a "temporary variable" So this line:

    Code:
    MyClass self() { return *this; }
    actually attempts to create a copy of *this to return. The copy is temporary and is destroyed right after it is returned. This is why the destructor was called.

    on the other hand:
    Code:
    MyClass& self() { return *this; }
    This does not create a temporary. It is a reference to *this. Of course there's really no reason to do this one because an assignment would be no different in either of these cases:

    MyClass instance;
    MyClass & firstref = instance.self();
    MyClass & secondref = instance;
    "You are stupid! You are stupid! Oh, and don't forget, you are STUPID!" - Dexter

  4. #4
    Normal vector Carlos's Avatar
    Join Date
    Sep 2001
    Location
    Budapest
    Posts
    463
    Thank for your answers lyx and FillYourBrain.

    Originally posted by FillYourBrain
    Of course there's really no reason to do this one because an assignment would be no different in either of these cases:

    MyClass instance;
    MyClass & firstref = instance.self();
    MyClass & secondref = instance;
    The purpose was to overload the operator [] and =, to create an array class which is able to handle e.g. common errors like overindexing.

    Code:
    MyArray::MyArray( unsigned int arraySize_in )
    {
    	if( arraySize_in == 0 
    		|| arraySize_in >= MAX_ARRAY_SIZE_VALUE )
    	{
    		arraySize_in = MAX_ARRAY_SIZE_VALUE;
    	}
    	myArray = new ( int[arraySize_in] );
    	for( unsigned int i = 0; i < arraySize_in; i++ )
    	{
    		myArray[i] = 0;
    	}
    
    	myIndex = 0;	
    	myLastIndex = arraySize_in - 1;
    }
    
    // copy constructor
    MyArray::MyArray( MyArray& array_in )
    {
    	myIndex = array_in.myIndex;
    	myLastIndex = array_in.myLastIndex;
    
    	myArray = new ( int[myLastIndex + 1] );	
    	for( unsigned int i = 0; i <= myLastIndex; i++ )
    	{
    		myArray[i] = array_in.myArray[i];
    	}
    	//*this = array_in;	
    }
    
    MyArray::~MyArray()
    {
    	delete[] myArray;
    	myArray = 0;
    	myIndex = 0;
    }
    
    MyArray& MyArray::operator [] ( int index_in )
    {
    	// range check
    	if ( index_in > myLastIndex )
    	{
    		myIndex = myLastIndex;
    	}
    	else
    	{
    		myIndex = index_in;		
    	}
    	return *this;
    }
    
    void MyArray::operator = ( const int val_in )
    {
    	myArray[myIndex] = val_in;
    }
    This way, the following code part will never cause problems:

    Code:
    	MyArray anArray(20);
    	anArray[120] = 12;
    Last edited by Carlos; 09-24-2003 at 07:58 AM.

  5. #5
    Amateur
    Join Date
    Sep 2003
    Posts
    228
    I think that standard containers implement methods that allow you to do safe indexing. I don't have much knowledge in STL but the BS says that at() method is used to do range controled indexing.

  6. #6
    pronounced 'fib' FillYourBrain's Avatar
    Join Date
    Aug 2002
    Posts
    2,297
    just store the size of the array. This will allow you to do a check on your operator=()
    Code:
    void MyArray::operator = ( const int val_in )
       {
       if(val_in < m_arrsize)
          myArray[val_in] = val_in;
       }
    Last edited by FillYourBrain; 09-24-2003 at 08:08 AM.
    "You are stupid! You are stupid! Oh, and don't forget, you are STUPID!" - Dexter

  7. #7
    Normal vector Carlos's Avatar
    Join Date
    Sep 2001
    Location
    Budapest
    Posts
    463
    Originally posted by FillYourBrain
    just store the size of the array. This will allow you to do a check on your operator=()
    Code:
    void MyArray::operator = ( const int val_in )
       {
       if(myIndex < m_arrsize)
          myArray[myIndex] = val_in;
       }
    And where to get myIndex from?? Right that's the purpose of [] operator redefinition. It returns *this just because the object type is needed as = operator is also redefined.

  8. #8
    Normal vector Carlos's Avatar
    Join Date
    Sep 2001
    Location
    Budapest
    Posts
    463
    Originally posted by lyx
    I think that standard containers implement methods that allow you to do safe indexing. I don't have much knowledge in STL but the BS says that at() method is used to do range controled indexing.
    Of course STL would do it, however I intend to create a good example on operator overloading. On the other hand, I think sometimes is easier to implement your own class for such purposes rather then using STL.

  9. #9
    pronounced 'fib' FillYourBrain's Avatar
    Join Date
    Aug 2002
    Posts
    2,297
    I changed that in my post. Just used the wrong variable name. No big deal there.

    by the way, if you index outside of the boundaries of vector it will crash.
    "You are stupid! You are stupid! Oh, and don't forget, you are STUPID!" - Dexter

  10. #10
    pronounced 'fib' FillYourBrain's Avatar
    Join Date
    Aug 2002
    Posts
    2,297
    I really should say, unexpected results like returning a *this for indexing into an array of ints doesn't make much sense. What's the person going to do with that information?
    "You are stupid! You are stupid! Oh, and don't forget, you are STUPID!" - Dexter

  11. #11
    Normal vector Carlos's Avatar
    Join Date
    Sep 2001
    Location
    Budapest
    Posts
    463
    Originally posted by FillYourBrain
    I really should say, unexpected results like returning a *this for indexing into an array of ints doesn't make much sense. What's the person going to do with that information?
    *this is only returned in order to correctly evaluate the = redefined operator.
    Code:
    	MyArray anArray(20);
    	anArray[120] = 12;
    When going to this line,
    anArray[120] = 12;

    first operator [] is evaluated, whereas myIndex is set to max allowed value (as it exceeds the allowed range, which is 0-19).
    myIndex gets the value myLastIndex, which is 19.
    *this is returned, so the redefined operator = from class MyArray is evaluated:

    myArray[19] = 12;

    But I got your problem - what happens in this case:

    int y = myArray[15];

    Well, nothing, it won't compile.
    Last edited by Carlos; 09-24-2003 at 08:19 AM.

  12. #12
    pronounced 'fib' FillYourBrain's Avatar
    Join Date
    Aug 2002
    Posts
    2,297
    but it's not correct.

    myArray[num]

    should return a reference to the type stored in the array. NOT the array class itself.
    "You are stupid! You are stupid! Oh, and don't forget, you are STUPID!" - Dexter

  13. #13
    Amateur
    Join Date
    Sep 2003
    Posts
    228
    I see, it is an example.
    Um... for the use of the STL, I don't use it.

    Anyway, I was thinking the same as FillYourBrain but he posted before I do. ^^

  14. #14
    Normal vector Carlos's Avatar
    Join Date
    Sep 2001
    Location
    Budapest
    Posts
    463
    Originally posted by FillYourBrain
    but it's not correct.

    myArray[num]

    should return a reference to the type stored in the array. NOT the array class itself.
    As I told you, this was meant to be an example on operator overloading.

    I overloaded () to return the given element of the array, but a getAt( int index_in ) or setAt( int index_in ) would also do it.
    This way there's no possibility to exceed the array range, which might be more important.

    Instead of:

    int y = anArray[15];

    use

    int y = anArray(15);

    or

    int y = anArray.GetAt(15);

    Or you have better ideas on preventing range excess in:

    anArray[ index ] = value;

    ?
    Last edited by Carlos; 09-24-2003 at 08:34 AM.

  15. #15
    pronounced 'fib' FillYourBrain's Avatar
    Join Date
    Aug 2002
    Posts
    2,297
    the return value isn't even used in this example:

    anArray[ index ] = value;


    so I have difficulty following you. returning *this accomplished nothing here.
    "You are stupid! You are stupid! Oh, and don't forget, you are STUPID!" - Dexter

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. What exactly is iterator returned by .end()?
    By pheres in forum C++ Programming
    Replies: 21
    Last Post: 12-09-2008, 09:50 AM
  2. Replies: 12
    Last Post: 10-16-2008, 02:49 PM
  3. How can the focus be returned to previous window?
    By wow in forum Windows Programming
    Replies: 5
    Last Post: 02-29-2008, 03:00 PM
  4. cannot find -lpcap collect2: ld returned 1 exit
    By nasim751 in forum C Programming
    Replies: 0
    Last Post: 02-12-2008, 12:37 AM
  5. Varible is different once returned.
    By epoch in forum C++ Programming
    Replies: 2
    Last Post: 01-04-2003, 02:45 AM