Calling delete on variable allocated on the stack
No, it is not safe to call delete
on a stack-allocated variable. You should only call delete
on things created by new
.
- For each
malloc
orcalloc
, there should be exactly onefree
. - For each
new
there should be exactly onedelete
. - For each
new[]
there should be exactly onedelete[]
. - For each stack allocation, there should be no explicit freeing or deletion. The destructor is called automatically, where applicable.
In general, you cannot mix and match any of these, e.g. no free
-ing or delete[]
-ing a new
object. Doing so results in undefined behavior.
What is the use of delete this?
"delete this" is commonly used for ref counted objects. For a ref counted object the decision of when to delete is usually placed on the object itself. Here is an example of what a Release method would look like [1].
int MyRefCountedObject::Release() {
_refCount--;
if ( 0 == _refCount ) {
delete this;
return 0;
}
return _refCount;
}
ATL COM objects are a prime example of this pattern.
[1] Yes I realize this is not thread safe.
Strange behavior of delete keyword in javascript
Your question is more related to the fact that some types are assigned by value and others by reference.
In a quick summary
Primitive types are assigned by value (Boolean, Null, Undefined, Number, String, Symbol (new in ES 6))
Non Primitive types are assigned by reference (Object, Array , Functions)
Example: Primitive types
let a = 1;
let b = a;
console.log(a); // 1
console.log(b); // 1
b = 2;
console.log(a); // 1
console.log(b); // 2
As you can see changing b
will not affect a
because number is assigned by value.
Example: Non Primitive types
let a = { name: 'Amr' };
let b = a;
console.log(a); // { name: 'Amr' };
console.log(b); // { name: 'Amr' };
b.name = "John";
console.log(a); // { name: 'John' };
console.log(b); // { name: 'John' };
As you can see changing b
affected the value of a
because it is assigned by reference, this is similar to your example, the issue is not related to delete
but it is related to the fact that objects are assigned by reference so deleting key from b
will affect a
Cloning:
in some situations you will need to clone your non primitive type object and not mutating the current one, you can do that using the following way:
ES5
var clone = Object.assign({}, obj);
ORvar clone = JSON.parse(JSON.stringify(obj));
ES6
var clone = { ...obj };
now updating clone
will not affect obj
Finally You can read more about this topic in this link it can give you a better understanding on how this works with memory assignment illustrations
Is delete allowed to modify its parameter?
Before the deletion, ptr
's value was valid. After the deletion, the value was invalid. Therefore the value changed. Valid values and invalid values are mutually exclusive -- a value cannot be simultaneously valid and invalid.
Your question has a basic misconception; you're conflating these two different concepts:
- The value of a variable
- The representation of a variable in memory.
There isn't a one-to-one correspondence between these two things. The same value may have multiple representations, and the same representation may correspond to different values.
I think the gist of your question is: can delete ptr;
change the representation of ptr
?. To which the answer is "Yes". You could memcpy the deleted pointer into a char array, inspect the bytes, and find them all to be zero-valued bytes (or anything else). This is covered in the standard by C++14 [basic.stc.dynamic.deallocation]/4 (or C++17 [basic.stc]/4):
Any other use of an invalid pointer value has implementation-defined behavior.
It's implementation-defined and the implementation could define that inspecting the bytes gives bytes with value zero.
Your code snippet relies on implementation-defined behaviour. "Valid code" isn't terminology used by the Standard, but the code might not remove the intended item from the hash table.
As alluded to by Stroustrup, this is an intentional design decision. An example usage would be a compiler in debug mode setting deleted pointers to a particular representation, so that it can raise a runtime error if a deleted pointer is subsequently used. Here's an example of that principle in action for uninitialized pointers.
Historical note: In C++11 this case was undefined, rather than implementation-defined. So the behaviour of using a deleted pointer was identical to the behaviour of using an uninitialized pointer. In the C language, freeing memory is defined as putting all pointers to that memory into the same state as an uninitialized pointer has.
Why does calling delete instead of delete[] on an array of class objects cause heap corruption?
It is undefined behavior to call delete
on a pointer created with new[]
. The basic issue is that when you call new[]
it needs to allocate extra space to store the number of elements in the array, so that when you call delete []
it knows how many elements to destroy.
The library will allocate space for the management data in addition to the needed space for the real objects. It will then perform all initialization and return a pointer to the first element, which is not aligned with the block of memory retrieved from the OS.
[header][element1,element2...]
^ ^
| \_ pointer returned by new[]
|
\_ pointer returned by the allocator
On the other hand, new
and delete
don't store any extra information.
When you call delete[]
it moves the pointer back, reads the count, calls the destructors and deallocates using the original pointer. When you call delete, it calls the destructor for the single object and passes the pointer back to the allocator. If the pointer was created through a call to new[]
, then the pointer that is returned to the allocator is not the same pointer that was allocated and the deallocation fails.
delete[] with different type undefined behaviour?
Yes, the behaviour is undefined.
The pointer passed to delete[]
must be the same type as the one you get back from new[]
.
Note that for delete
and new
, the pointer submitted to delete
is allowed to be related by polymorphism.
Related Topics
Why Use Prefixes on Member Variables in C++ Classes
Osx - Replace Gcc Version 4.2.1 with 4.9 Installed via Homebrew
How to Create a Simple Qt Console Application in C++
Accessing Protected Members of Superclass in C++ with Templates
Checking If an Iterator Is Valid
Assignment Operator Inheritance
How to Make a Portable Isnan/Isinf Function
Image Scaling and Rotating in C/C++
Decltype as a Return Type in Class Member Function
What Does _Declspec(Dllimport) Really Mean
How to Turn Unsigned Char into Char and Vice Versa
Template Function as a Template Argument
Why Aren't Static Const Floats Allowed
How to Make Elements of Vector Unique? (Remove Non Adjacent Duplicates)