0

I have small piece of code:

#include <iostream>
using namespace std;

int main() 
{
    int *p = new int(10);

    if(p != NULL)
    {
        cout<<"Deleted dynamic allocated memory"<<endl;
        delete p;
    }

    if(p == NULL)
    {
        cout<<"NULL"<<endl;
    }
    else
    {
        cout<<"Not NULL"<<endl;
    }
    return 0;
}

After deleting dynamic allocated memory using delete operator, Why compilers do not assigned NULL to pointer(like p = NULL) automatically?

msc
  • 33,420
  • 29
  • 119
  • 214
  • 3
    For the same reason a member function isn't dynamically dispatched unless explicitly request it to be. C++ doesn't make you pay for what you don't use. – StoryTeller - Unslander Monica Jul 17 '17 at 11:24
  • 3
    You can delete something, which is not an lvalue. For example, `delete p+1`. In this case, you cannot set anything to `nullptr`. – geza Jul 17 '17 at 11:26
  • imho it is good that compilers dont do it. To my experience most confusion about pointers for beginners is due to thinking there would be some magic link between a pointer and the pointee and making `delete p` set `p` to `0` just feeds this misunderstanding. – 463035818_is_not_an_ai Jul 17 '17 at 11:31

4 Answers4

9
  1. It would often be unnecessary, particularly in well-written code.

  2. It could hide away bugs.

  3. delete p; would be syntactically idiosyncratic if it modified its argument.

On (1) it would be particularly wasteful with std::unique_ptr.

In other words, burdening the programmer with this job if necessary is the right thing to do.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • on 3) afaik `delete p` is allowed to set `p` to `0`. And I remember Soustroup saying somewhere that he wished that it was mandatory (however I disagree with him on that point) – 463035818_is_not_an_ai Jul 17 '17 at 11:24
  • @tobi303: You are indeed correct. I'm glad Stroustrup did not get his way on this. – Bathsheba Jul 17 '17 at 11:24
  • @tobi303 - What Bathsheba said. The looser contract of a mere "indeterminate value" makes for better machine code. – StoryTeller - Unslander Monica Jul 17 '17 at 11:25
  • @StoryTeller I get the point, I was just a bit confused because 3) reads like `delete` does not modify its argument, but in fact it is allowed to do so – 463035818_is_not_an_ai Jul 17 '17 at 11:27
  • @tobi303 - I think what point (3) means is that the syntax for `delete` doesn't suggest `p` *could* be modified. – StoryTeller - Unslander Monica Jul 17 '17 at 11:29
  • @StoryTeller but `delete` is allowed to modify `p`. Nevermind, I think in fact we agree on the point and its just about the wording... – 463035818_is_not_an_ai Jul 17 '17 at 11:33
  • 2
    @tobi303 - Just one last thing. You know `delete` can modify `p`, and I know that. Anybody who's read the standard or worked enough with C++ knows that. But from a pure syntax perspective, I don't think it's obvious. – StoryTeller - Unslander Monica Jul 17 '17 at 11:34
  • 1
    @StoryTeller finally I got it. Thanks for your patience ;) – 463035818_is_not_an_ai Jul 17 '17 at 11:36
  • @StoryTeller: "You know `delete` can modify `p`". Where is this written in the standard? I cannot find it. – geza Jul 17 '17 at 11:53
  • @geza - [new.delete.single](http://eel.is/c++draft/new.delete.single#10) for instance. Note the `ptr` is ["invalid"](http://eel.is/c++draft/basic.compound#3.4) afterwards. Which means a conforming C++ compiler can still modify it however it likes after `delete` was successfully executed. – StoryTeller - Unslander Monica Jul 17 '17 at 12:11
  • @StoryTeller: Hmm. `void operator delete(void* ptr) noexcept;` If I wanted to be picky, `ptr` is a local variable here. So definitely doesn't modify my original variable. What if my expression for `delete` is not an lvalue? – geza Jul 17 '17 at 12:23
  • @geza - The value itself (address if you will) becomes invalid (there are several links to follow about invalid pointer values). An implementation knowing the value is now invalid may do whatever with the pointer itself. – StoryTeller - Unslander Monica Jul 17 '17 at 12:26
  • @StoryTeller: yes, ok, but where is this written in the standard? new.delete.single refers to `ptr`, which is not the variable at `delete XXX`. I've read all the available material here in SO, but haven't found an answer. It is not a common knowledge, I think. Even in this answer: "`delete p;` would be syntactically idiosyncratic if it modified its argument.". This doesn't mean to me that `delete` is allowed to modify its argument. – geza Jul 17 '17 at 12:32
  • 1
    @geza - *(shrug)* Then you'll have to read more. The value is invalid, even comparing the pointer to `nullptr` is not allowed without UB. If you can't expect *any* observable behavior, it automatically means great leeway for the implementation. – StoryTeller - Unslander Monica Jul 17 '17 at 12:41
  • 1
    "The value is invalid, even comparing the pointer to nullptr is not allowed without UB" is **very, very** important if you like to write truly portable code. – Bathsheba Jul 17 '17 at 12:43
  • @StoryTeller: what do you think, even `memcpy(buffer, &ptr, sizeof(ptr))`; is disallowed? Or directing a `const char *a` to `&ptr`, and reading from `a`? – geza Jul 17 '17 at 13:11
  • @geza - I don't have to think. [It's completely up to the implementation](http://eel.is/c++draft/basic.stc#4). I was wrong in one thing, which was thinking it's all UB. An implementation is in fact obligated to document what it does. But if you read the [footnote](http://eel.is/c++draft/basic.stc#footnote-37), what you suggested could cause a run-time error. – StoryTeller - Unslander Monica Jul 17 '17 at 13:16
  • @StoryTeller: yes, but this time I don't copy the pointer as a pointer, but as a memory-blob. So, does this mean, that I cannot `memcpy` a variable? Or, if I have a struct, which happen to have a pointer which has invalid value, then I cannot copy this struct? Does that mean that I cannot observe an invalid pointer value with a `char *`? It doesn't sound too good. Thanks for the patience, btw :) – geza Jul 17 '17 at 13:23
  • @geza - Remember the leeway the implementation has? [Assume the character types have trap values](https://stackoverflow.com/questions/24034296/can-a-plain-char-possibly-have-trap-values). Then nothing is stopping the implementation from overwriting `ptr` with those. And you'll get traps for a memory-blob as well. Don't think of it as a bad thing. If you have an invalid pointer value running around in your program, that's usually indicative of a bug. – StoryTeller - Unslander Monica Jul 17 '17 at 13:28
  • @StoryTeller: I've asked this as a question: https://stackoverflow.com/questions/45149756/is-delete-allowed-to-modify-its-parameter – geza Jul 17 '17 at 17:24
2

Because it is extra work (= more clock cycles, less performance), that is usually not needed.

Bart Friederichs
  • 33,050
  • 15
  • 95
  • 195
2

If your design calls for NULLing a pointer to indicate that it no longer points at something useful, you can add code to do that. But that should not be the default, because it can be insufficient and pointless.

NULL pointers don't solve every possible problem:

int *ip = new int;
int *ip1 = ip;
delete ip;
if (ip1)
    *ip1 = 3; // BOOM!

And they are often pointless:

struct s {
    int *ip;
    s() : ip(new int) {}
    ~s() { delete ip; } // nobody cares if ip is NULL, 'cause you can't see it
};
Pete Becker
  • 74,985
  • 8
  • 76
  • 165
0

They are allowed to do so, but it isnt mandatory. I think the reason they dont do it consitently is because anyhow you cant rely on it. For example consider this:

int* a = new int(3);
int* b = a;
delete a;
/// ....
if (b != 0) {              /// assume b is either null or points to something valid
     std::cout << *b;      /// ups 
}
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185