C++ new delete操作
黄舟
黄舟 2017-04-17 12:04:22
0
4
571

如果代码如下:
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.

黄舟
黄舟

人生最曼妙的风景,竟是内心的淡定与从容!

reply all(4)
Ty80

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

小葫芦

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

Updated at 2015-9-4 00:20

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
}

The process of delete

  1. Calls the rawMemdestructor 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.

  2. 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.

The process of delete[]

  1. 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! ).

  2. Iteratively call these N destructors.

  3. operator deleteRelease 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.

Incorrect use

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, deletean array of primitive types will not have particularly bad effects. The biggest problem is that the subsequent memory is not recycled. But deletean 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.

Ty80

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.

阿神

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

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template