GIDForums  

Go Back   GIDForums > Computer Programming Forums > C++ Forum
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 08-May-2007, 01:29
tufan tufan is offline
Junior Member
 
Join Date: Aug 2006
Posts: 32
tufan is on a distinguished road

destruction function


i have a problem with the destruction function.it runs somewhere that i don't expect.I tried with a bunch number of compilers.same result.can u tell me the way it makes sense?

CPP / C++ / C Code:
#include <iostream>
using namespace std;
class String
{
private:
    char* str;
public:
    String()
    {  }
    String(char* s)
    {
        int length = strlen(s);
        str = new char[length+1];
        strcpy(str, s);
    }   //after here it jumps
    ~String()       //here
    {
        cout << "Deleting str\n";
        delete[] str;
    }
    void display()
    {
        cout << str << endl;
    }
    void upit();
};
void String::upit()
{
    char *p=str;
    while (*p)
    {
        *p=toupper(*p);
        p++;
    }
}
int main()
{
    String s1;
    s1="abcdef";
    s1.upit();

    s1.display();

    cout<<"\n";
    system("pause");
    return 0;
}

  #2  
Old 08-May-2007, 10:20
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,648
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: destruction function


Quote:
Originally Posted by tufan
i have a problem with the destruction function.it runs somewhere that i don't expect.

Make the program tell you where it goes and when it goes there:

CPP / C++ / C Code:
#include <iostream>
using namespace std;
class String
{
private:
    char* str;
public:
    String()
    { cout << "*** A. In constructor()" << endl << endl; }

    String(char* s)
    {
        int length = strlen(s);
        cout << "*** B1. In constructor(char *)" << endl;
        str = new char[length+1];
        strcpy(str, s);
        cout << "*** B2. Leaving constructor" << endl << endl;
    }

    ~String()
    {
        cout << "*** C1. In destructor." << endl;
        delete[] str;
        cout << "*** C2. Leaving destructor." << endl << endl;
    }

    void display()
    {
        cout << "*** D1. In display(): ";
        cout << str << endl;
        cout << "*** D2. Leaving display()" << endl << endl;
    }
    void upit();
};
void String::upit()
{
    char *p=str;
    while (*p)
    {
        *p=toupper(*p);
        p++;
    }
}
int main()
{
    cout << "1a. Before first declaration." << endl;
    String s1;
    cout << "1b. After  first declaration." << endl << endl;

    cout << "2a. Before assignment." << endl;
    s1 = "abcdef";
    cout << "2b. After  assignment." << endl << endl;

    cout << "3a. Before upit()." << endl;
    s1.upit();
    cout << "3b. After  upit()." << endl << endl;

    cout << "4a. Before display()." << endl;
    s1.display();
    cout << "4b. After  display()." << endl << endl;

    return 0;
}

Output:

Code:
1a. Before first declaration. *** A. In constructor(). 1b. After first declaration. 2a. Before assignment. *** B1. In constructor(char *) *** B2. Leaving constructor. *** C1. In destructor. *** C2. Leaving destructor. 2b. After assignment. 3a. Before upit(). 3b. After upit(). 4a. Before display(). *** D1. In display(): ABCDEF *** D2. Leaving display() 4b. After display().

Note that the stuff displayed at step after 4a may be garbage or not. The program may crash (or not) as it exits.

You will find that the problem arises from the assignment statement s1 = "abcdef";
(That's where your unexpected destructor is called.)


What happens is:
1. A constructor is called to make a temporary String object for the string literal.

2. The constructor allocates storage for a buffer and copies the string literal into the temporary object's str member.

3. The assignment is made: The value of s1.str is set equal to the address of the buffer containing the copy of the string literal. This is the operation of the default assignment operator for any class: a so-called "shallow copy".

4. The destructor is called for the temporary object (which deallocates the storage, and makes the value of s1.str invalid).

When you have a class member that is a pointer and a constructor or other member function allocates storage and assigns its address to that pointer, then you have a problem with an assignment statement.

If you don't create an assignment operator (overload the '=' operator), the default assignment operator simply copies the object. That is, the pointer value of the object on the left-hand side of the assignment is set equal to the value of the pointer on the right-hand side. (So it won't work if the object on the right hand side goes out of scope. And it won't work the way you need for it to work in any case.)

The solution: make an overloaded assignment operator that actually allocates new storage and copies the contents rather than just using the default assignment operator.

If you implement an overloaded assignment operator with debugging print statements along the lines that I showed above, you might see something like:

Code:
1a. Before first declaration. *** A. In constructor(). 1b. After first declaration. 2a. Before assignmemt. *** B1. In constructor(char *) *** B2. Leaving constructor. E1. In overloaded assignment. E2. Leaving overloaded assignment. *** C1. In destructor. *** C2. Leaving destructor. 2b. After assignmemt. 3a. Before upit(). 3b. After upit(). 4a. Before display(). *** D1. In display(): ABCDEF *** D2. Leaving display() 4b. After display(). *** C1. In destructor. *** C2. Leaving destructor.

The sequence from 2a through 2b shows what actually happens for an assignment like the one that you used in your program.

Of course this is OK for illustration of the sequence of operations and for showing why you (usually) must overload the assignment operator in cases like this. For practical programs like this, you would use a std::string rather than an pointer to char for the class member. There are other times when you might actually need a pointer (to something) as a class member, and the things shown in this simple illustration will apply.


Regards,

Dave
 
 

Recent GIDBlogLast Week of IA Training by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Message Class TransformedBG C++ Forum 5 29-Nov-2006 21:28
[Include] Doubly-linked List dsmith C Programming Language 6 14-Apr-2006 13:12
[Tutorial] Function Pointers aaroncohn C++ Forum 4 17-Feb-2006 11:33
[GIM] gim.h dsmith C Programming Language 0 18-Jan-2005 08:48
Revising Script style ?????? pepee MySQL / PHP Forum 4 14-Apr-2004 04:59

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 23:51.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.