what's the difference between delete ptr and ptr=0 -dont they accomplish the same

Discussion in 'C++' started by Sid, Jul 28, 2004.

  1. Sid

    Sid Guest

    Hi,
    I was going through this reference code and playing around with it.
    The code (shown below) shows a class that represents a stack of string
    pointers

    In the code below in particular in the pop function, the code works
    when I set stack[index]=0 but when I say delete stack[index] the code
    compiles but does not execute -I am only trying to "delete
    stack[index]" after I have copied the relevant data pointed by it
    into variable "rv", so why is this program not allowing me to free
    stack[index] (which is nothing but a pointer to a string) ?.

    Also, when I comment the stack[index] and the delete stack[index], the
    code executes to completion but doesn't this actually create a memory
    leak since stack[index] is never deallocated or freed and if so how is
    the program executing to completion without any errors ?

    I would greatly appreciate any feedback.



    #include <string>
    #include <iostream>
    using namespace std;

    class StringStack {
    static const int size = 100;
    const string* stack[size];
    int index;
    public:
    StringStack();
    void push(const string* s);
    const string* pop();
    };

    StringStack::StringStack() : index(0) {
    memset(stack, 0, size * sizeof(string*));
    }

    void StringStack::push(const string* s) {
    if(index < size)
    stack[index++] = s;
    }

    const string* StringStack::pop() {
    if(index > 0) {
    const string* rv = stack[--index];
    stack[index] = 0; // this works
    //delete stack[index]; // doesn't work
    return rv;
    }
    return 0;
    }

    string iceCream[] = {
    "pralines & cream",
    "fudge ripple",
    "jamocha almond fudge",
    "wild mountain blackberry",
    "raspberry sorbet",
    "lemon swirl",
    "rocky road",
    "deep chocolate fudge"
    };


    const int iCsz =
    sizeof iceCream / sizeof *iceCream;

    int main() {
    cout << "size of iceCream="<< sizeof iceCream << endl;
    cout << "size of *iceCream="<< sizeof *iceCream << endl;

    StringStack ss;
    for(int i = 0; i < iCsz; i++)
    ss.push(&iceCream);
    const string* cp;
    while((cp = ss.pop()) != 0)
    cout << *cp << endl;
    } ///:~
     
    Sid, Jul 28, 2004
    #1
    1. Advertising

  2. On 28 Jul 2004 00:31:46 -0700, Sid <> wrote:

    > Hi,
    > I was going through this reference code and playing around with it.
    > The code (shown below) shows a class that represents a stack of string
    > pointers
    >
    > In the code below in particular in the pop function, the code works
    > when I set stack[index]=0 but when I say delete stack[index] the code
    > compiles but does not execute -I am only trying to "delete
    > stack[index]" after I have copied the relevant data pointed by it
    > into variable "rv", so why is this program not allowing me to free
    > stack[index] (which is nothing but a pointer to a string) ?.


    Nowhere in your code do you use new, so you don't need to use delete.

    >
    > Also, when I comment the stack[index] and the delete stack[index], the
    > code executes to completion but doesn't this actually create a memory
    > leak since stack[index] is never deallocated or freed and if so how is
    > the program executing to completion without any errors ?


    There is no memory leak because you never allocated any memory. For every
    time you call new you should also call delete, if you never call new, you
    never need to call delete.

    john
     
    John Harrison, Jul 28, 2004
    #2
    1. Advertising


  3. > void StringStack::push(const string* s) {
    > if(index < size)
    > stack[index++] = s;
    > }


    You are aware that you only store pointers here, are you? If you do
    this:

    string s = new string("Hello");
    StringStack st;
    st.push(s);
    delete s; // Now you've got a problem when trying to use st.pop();




    > string iceCream[] = {
    > "pralines & cream",
    > "deep chocolate fudge"
    > };


    Now you make a static field:

    int *a = {3,4,5};

    you cannot delete [] a. You would have to use:
    int *a = new int[3];



    What do you want to do? Store an array of strings or pointers to
    strings that _must_ exist all the time the array exists? Don't
    reinvent the wheel.

    #inlcude <stack>
    #include <string>

    std::stack<std::string> AStringStack;
    _or_
    std::stack<std::string*> APointerStack;

    HTH,

    --
    -Gernot
    int main(int argc, char** argv) {printf
    ("%silto%c%cf%cgl%ssic%ccom%c", "ma", 58, 'g', 64, "ba", 46, 10);}

    ________________________________________
    Looking for a good game? Do it yourself!
    GLBasic - you can do
    www.GLBasic.com
     
    Gernot Frisch, Jul 28, 2004
    #3
  4. > I am only trying to "delete
    > stack[index]" after I have copied the relevant data pointed by it
    > into variable "rv", so why is this program not allowing me to free
    > stack[index] (which is nothing but a pointer to a string) ?


    You don't copy the data "stack[--index]" points to - you only copy the
    pointer itself.

    > class StringStack {
    > static const int size = 100;
    > const string* stack[size];
    > int index;
    > public:
    > StringStack();


    Having no destructor here works for your "string iceCream[]" example,
    but iff the string instances are allocated on the free store, usage of "StringStack"
    will likely lead to memory leaks basically because of the following:
    If the user assumes that "push()" and "pop()" both change ownership over
    the "string" instance (in the sense, that after "push()" ownership is held
    by the instance of "StringStack" instead of the caller and after "pop()" the
    caller again own the "string" instance instead of the "StringStack"), then noone
    ever "delete"s the string instances on destruction of a non-empty "StringStack".

    > void push(const string* s);
    > const string* pop();
    > };


    > void StringStack::push(const string* s) {
    > if(index < size)
    > stack[index++] = s;
    > }


    Just a comment: You should somehow signal "index>=size" to the caller -
    either by throwing an exception or by means of a "bool" return value.

    In my opinion the "push()" should clearly change ownership over the "string"
    instance from the caller to the "StringStack" instance as already indicated above.

    > const string* StringStack::pop() {
    > if(index > 0) {
    > const string* rv = stack[--index];
    > stack[index] = 0; // this works
    > //delete stack[index]; // doesn't work
    > return rv;
    > }
    > return 0;
    > }


    "delete" can't work - as said "const string* rv = stack[--index];" only
    copies the pointer, not the string. So "pop()" should clearly change ownership
    over the "string" instance from the "StringStack" instance to the caller
    as already indicated above. Another thing is, that "stack[index] = 0;" doesn't
    serve for any purpose here.

    As others have posted, consider to go for "std::stack<>" instead of "StringStack",
    but note that if you go for "std::stack< std::string * >" the above comment on a
    missing destructor also applies, because standard containers don't take ownership
    because of their value semantics.

    Cheers,
    Philipp.
     
    Philipp Bachmann, Jul 28, 2004
    #4
  5. Sid

    JKop Guest

    int* p_number;

    p_number = 0;

    p_number = reinterpret_cast<int*>(5678);

    p_number = reinterpret_cast<int*>(8764);


    That's exactly like:


    int number;

    number = 0;

    number = 5678;

    number = 8764;


    "p_number" is a variable just like "number".

    The type of "number" is "int"

    The type of "p_number" is "int*".

    They're both variables and they're value can be set and read.


    As for "delete", it's like a function that takes in a memory address as an
    argument. It frees any memory that has been allocated at this address. It
    can only be used in conjunction with "new".

    int* p_number = 0;

    p_number = reinterpret_cast<int*>(8888);

    delete p_number;


    Here, "delete" is being called with the value of "p_number" as a parameter.
    The value of "p_number" is the memory address 8888.

    As no memory was allocated by "new" at that address, what we have here is
    bad code, it's "undefined behaviour". Here's a legitamate use of "delete":


    int* p_number = new int;

    //Now, p_number contains a value, a memory address, let's say it's 98733

    *p_number = 56;

    SomeFuncThatTakesInt(*p_number); //Is given 56

    SomeFuncThatTakesIntPointer(p_number); //Is given 98733

    delete p_number; //Is given 98733


    Here, "delete" is called and given the value stored inside the variable
    "p_number", which is 98733. It deallocates the memory at that address which
    was allocated via "new". This is how "new" and "delete" are supposed to
    work. So, in summation:


    p_number = 0;

    All it does is change the value of a variable. It doesn't allocate or
    deallocate memory.

    p_number = new int;

    "new" is like a function that returns a memory address. "new" allocates
    memory and then gives you the address of that memory.

    delete p_number;

    "delete" is like a function that takes a memory address as an argument
    (except there's no parenthesis!). It deallocates memory according to the
    memory address it's supplied with. If memory was previously located at that
    address via "new", then all is fine and dandy; if the contrary, then it's
    Undefined Behaviour.


    Hope that helps.

    And just remember that a pointer variable is just like any other variable.
    Where an "int" stores an integer number, an "int*" stores a memory address.
    Just as an example, on WinXP, an "int" takes up 32 bits in memory, and an
    "int*" takes up 32 bits in memory. You could have something like a "double",
    which takes up maybe 80 bits in memory, but a "double*" will only take up 32
    bits, because 32 bits is all that's needed to store a memory address on
    WinXP.


    -JKop
     
    JKop, Jul 28, 2004
    #5
  6. Sid

    Sid Guest

    THANKS A BUNCH FOLKS - I appreciate your time and effort.


    JKop <> wrote in message news:<GZQNc.5678$>...
    > int* p_number;
    >
    > p_number = 0;
    >
    > p_number = reinterpret_cast<int*>(5678);
    >
    > p_number = reinterpret_cast<int*>(8764);
    >
    >
    > That's exactly like:
    >
    >
    > int number;
    >
    > number = 0;
    >
    > number = 5678;
    >
    > number = 8764;
    >
    >
    > "p_number" is a variable just like "number".
    >
    > The type of "number" is "int"
    >
    > The type of "p_number" is "int*".
    >
    > They're both variables and they're value can be set and read.
    >
    >
    > As for "delete", it's like a function that takes in a memory address as an
    > argument. It frees any memory that has been allocated at this address. It
    > can only be used in conjunction with "new".
    >
    > int* p_number = 0;
    >
    > p_number = reinterpret_cast<int*>(8888);
    >
    > delete p_number;
    >
    >
    > Here, "delete" is being called with the value of "p_number" as a parameter.
    > The value of "p_number" is the memory address 8888.
    >
    > As no memory was allocated by "new" at that address, what we have here is
    > bad code, it's "undefined behaviour". Here's a legitamate use of "delete":
    >
    >
    > int* p_number = new int;
    >
    > //Now, p_number contains a value, a memory address, let's say it's 98733
    >
    > *p_number = 56;
    >
    > SomeFuncThatTakesInt(*p_number); //Is given 56
    >
    > SomeFuncThatTakesIntPointer(p_number); //Is given 98733
    >
    > delete p_number; //Is given 98733
    >
    >
    > Here, "delete" is called and given the value stored inside the variable
    > "p_number", which is 98733. It deallocates the memory at that address which
    > was allocated via "new". This is how "new" and "delete" are supposed to
    > work. So, in summation:
    >
    >
    > p_number = 0;
    >
    > All it does is change the value of a variable. It doesn't allocate or
    > deallocate memory.
    >
    > p_number = new int;
    >
    > "new" is like a function that returns a memory address. "new" allocates
    > memory and then gives you the address of that memory.
    >
    > delete p_number;
    >
    > "delete" is like a function that takes a memory address as an argument
    > (except there's no parenthesis!). It deallocates memory according to the
    > memory address it's supplied with. If memory was previously located at that
    > address via "new", then all is fine and dandy; if the contrary, then it's
    > Undefined Behaviour.
    >
    >
    > Hope that helps.
    >
    > And just remember that a pointer variable is just like any other variable.
    > Where an "int" stores an integer number, an "int*" stores a memory address.
    > Just as an example, on WinXP, an "int" takes up 32 bits in memory, and an
    > "int*" takes up 32 bits in memory. You could have something like a "double",
    > which takes up maybe 80 bits in memory, but a "double*" will only take up 32
    > bits, because 32 bits is all that's needed to store a memory address on
    > WinXP.
    >
    >
    > -JKop
     
    Sid, Jul 29, 2004
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. jakk
    Replies:
    4
    Views:
    12,639
  2. HeroOfSpielburg
    Replies:
    1
    Views:
    415
    Alf P. Steinbach
    Aug 6, 2003
  3. Jason

    difference between *ptr++ and ++*ptr ?

    Jason, May 15, 2005, in forum: C Programming
    Replies:
    19
    Views:
    6,670
    Chris Torek
    May 19, 2005
  4. hans christian

    newbie question: difference between (*ptr) and *ptr

    hans christian, Jun 11, 2006, in forum: C Programming
    Replies:
    5
    Views:
    769
    hans christian
    Jun 11, 2006
  5. AY
    Replies:
    4
    Views:
    2,262
Loading...

Share This Page