I don't know the details in Java, but here is what new and new[] do in C ++:
Allocate memory
When you have the expression new T or new T(args) , the compiler determines which function to call to get memory
- If type
T has a corresponding member operator new , which is called Otherwise, if the user has provided the corresponding global operator new , which is called.
If operator new cannot allocate the requested memory, it calls a new handler function, which you can set using set_new_handler . This function can free some space so that the distribution can succeed, it can interrupt the program or it can throw an exception like std::bad_alloc or get from it. By default, the new handler just throws std::bad_alloc .
The same thing happens for new T[n] , except that operator new[] is called to allocate memory.
Build the object accordingly. objects in newly allocated memory.
For new T(args) , the corresponding constructor of the object is called. If the constructor throws an exception, the memory is freed by calling the corresponding operator delete (which can be found in the same places as operator new )
For new T it depends if T is a POD (i.e., a built-in type or basically C struct / union) or not. If T is a POD, nothing happens, otherwise it is treated as new T() .
For new T[n] this also depends on whether T POD . Again, PODs are not initialized. For non-PODs, the default constructor, in turn, calls in order for each of the objects. If one default constructor of the object is generated, no additional constructors are called, but already constructed objects (which do not include the one whose constructor is simply thrown) are destroyed (i.e., have a destructor) in the reverse order. Then the memory is freed using the corresponding operator delete[] .
Returns a pointer to the newly created object (s). Note that for new[] pointer will most likely not point to the beginning of the allocated memory, because there will probably be some information about the number of allocated objects preceding the constructed objects, which is used by delete[] to find out how many objects to destroy .
In all cases, objects live until they are destroyed using delete ptr (for objects allocated with normal new ) or delete[] ptr (for objects created using the new T[n] array). If not added to a third-party library, there is no garbage collection in C ++.
Note that you can also directly call operator new and operator delete to allocate raw memory. The same is true for operator new[] and operator delete[] . However, note that even for those low-level functions, you can not mix calls, for example. by freeing memory with operator delete , which you allocated with operator new[] .
You can also create an object in the allocated memory (regardless of how you got it) with the so-called new placement. This is done by pointing to the raw memory pointer as the new argument, for example: new(pMem) T(args) . To destroy such an explicitly constructed object, you can directly call the object's destructor, p->~T() .
Posting new jobs by calling operator new , which takes a pointer as an optional argument and simply returns it. The same mechanism can also be used to provide other information for operator new overloads that take appropriate additional arguments. However, while you can define the appropriate operator delete , they are used only to clean up when the object throws an exception at build time. There is no placement deletion syntax.
Another use of the new layout syntax already provided by C ++ is not new. This parameter accepts the additional parameter std::nothrow and differs from the usual new only in that it returns a null pointer if the distribution fails.
Also note that new not the only memory management mechanism in C ++. On the one hand, there are functions C malloc and free . Although usually operator new and operator new[] simply call malloc , this is not guaranteed. Therefore, you cannot mix these forms (for example, by calling free pointer pointing to the memory allocated by operator new ). On the other hand, STL containers process their distributions through dispensers, which are objects that control the distribution / deallocation of objects, as well as the construction / destruction of objects in containers.
And finally, there are those objects whose lifetime is controlled directly by the language, namely the static and automatic lifetime. Automatic lifetime objects are distributed by simply defining a type variable in the local area. They are automatically created when the execution skips this line and is automatically destroyed when the execution leaves the scope (including its scope remains with the exception). Static lifetime objects are defined in the global / namespace area or in the local area using the static keyword. They are created when the program starts (global scope / namespace) or when their definition string is executed (local scope), and they live until the end of the program when they are automatically destroyed in the reverse order of construction.
As a rule, automatic or static variables should be preferable to dynamic allocation (i, e, everything that you allocate using new or allocators), because the compiler takes care of proper destruction, unlike dynamic allocation, where you have to do it yourself. If you have dynamically allocated objects, it is advisable that their life be controlled by automatic / static objects (containers, smart pointers) for the same reason.