如果代码如下:
int *p=new int (20);
delete []p;
这样时正确的我可以理解,为什么在编译器里运行如下代码同样是正确的呢?
int *p=new int (20);
delete p;//同样正确,原因呢?
…………………………………………………………………………………………………………
9.3 10:11更新
看到下面大家的解答稍微有些认识了,假如有类people
people *p=new people(20)
这个作何解释呢?
people *p=new people[20]
这个是对象数组,数组的大小为20.
PHP中文网2017-04-17 12:06:22
Maybe it’s a typo, or maybe you misunderstood: maybe the parentheses after int should be square brackets?
int *p1 = new int(20); // 这一句是分配一个 int 的空间并将其内容初始化为 20 。
int *p2 = new int[20]; // 这一句是分配 20 个 int 的空间。
In the above code snippet, p1 should be released using delete, and p2 should be released using delete[].
This will happen未定义行为
if new and delete do not correspond.
Specific to your environment, if you confirm that both situations are executed normally and there is no memory leak, you can explain it as follows:
Because the difference between new/delete and malloc/free mainly lies in whether to call the constructor/destructor.
The difference between delete and delete[] lies in how many times the destructor is called.
The basic There is no construction/destruction of types, so both usages get the same result in your environment.
However, this is still a case in point 未定义行为
that different compiler implementations handle this differently, and
the C++ standard makes no guarantees.
In addition to the link given by @harttle, the discussion in this link is also worth referring to: http://stackoverflow.com/questions/6953457/delete-and-delete-are-the-same-when-deleting-arrays
高洛峰2017-04-17 12:06:22
I understand what you mean. Do you think that delete
(not delete[]
) for arrays and single elements should be able to compile, right? It really shouldn't be. There is no such problem in modern programming languages. The problem lies in C++'s array pointer degradation.
C++ was originally started by Stroustrup to implement the object-oriented mechanism. For efficiency reasons, a new type system was not designed, but was extended based on C (C with classes). In this way, C++ inherits some low-level language features of C. For example: Arrays cannot be passed through parameters or return values, and pointers are always passed. As for whether the pointed content is an array or an element, the responsibility for maintenance falls on the developer.
The array name will be downgraded to the first element pointer in most cases, so the array name and element pointer have mutually compatible types. For example:
int arr[5];
int * p == arr; // 这是兼容的
void f1(int *);
f(arr); // 这也是兼容的
int* f2(){
int arr[2];
return arr; // 这也是兼容的
}
So delete
an array and delete
a pointer are syntactically exactly the same. So the compiler won't throw any errors, but runtime will throw undefined behavior . For more discussion of the delete
form, see http://harttle.com/2015/08/07/effective-cpp-16.html
The above answer is about why the compiler does not give warnings or errors, because the array name and element pointer are type-compatible. Now let’s add “What exactly happens when delete
and delete[]
are called?”
Usually the delete
keyword can be regarded as a function call + memory recycling process. You can override (override) the function call:
void operator delete(void *rawMem) throw(){
// 正确地重写new/delete较为困难,可以参见Effective Item 51、52
}
Calls the rawMem
destructor of the object on the memory pointed to by the parameter pointer . Of course, the destructor of a polymorphic class is generally a virtual function. In a normal implementation, all destructors at the class level will be called cascadingly. This is done by the compiler, before operator delete
above.
operator delete
completes the default (or customized) memory recycling, usually calling the free
keyword. Even if you don't overload operator delete
, C++ provides a global implementation.
Get the length N of the array. Different compilers have different implementations here, and the basic data types and objects are also different. The compiler may store an array length in the array header ( so the array size may be greater than the sum of the element sizes, and the first element address is not necessarily equal to the array address! ).
Iteratively call these N destructors.
operator delete
Release the memory of N elements.
Scott Meyers: Don’t assume any C++ memory layout, and don’t do any memory operations based on that assumption.
If delete
is used to recycle an array, or delete[]
is used to recycle elements, the runtime behavior is undefined. That is to say, the compiler can implement it however it wants. The C++ standard does not specify how to handle this situation.
But generally speaking, delete
an array of primitive types will not have particularly bad effects. The biggest problem is that the subsequent memory is not recycled. But delete
an object array often causes the program to exit abnormally. For example:
string* p = new string[4];
delete p;
On Mac with Homebrew gcc 5.1.0 there is a runtime error:
error for object 0x7fcd93c04b38: pointer being freed was not allocated
In short, if you use new
to apply for memory, use delete
to recycle it; if you use new []
to apply for memory, use delete[]
to recycle it. This all depends on consciousness, the compiler will not care about you.
PHP中文网2017-04-17 12:06:22
No error reported does not mean there will be no errors.
Simply put, delete []p
will perform the destruction operation of all objects in the p array one by one, but delete p
will not.
Search for more details yourself.
阿神2017-04-17 12:06:22
int *p=new int (20);
Isn’t this applying for an int space and initializing the value to 20? .
Do you want to say this?
int *p=new int [20];
This is the application array
p just points to a pointer. Whether it points to a single element or an array is up to the developer. The compiler will only release the array as the address of the array when [] is included