Difference between new operator in C++ and new operator in java

10,771

Solution 1

  • In C++, T * p = new T;...
  1. allocates enough memory for an object of type T,

  2. constructs an object of type T in that memory, possibly initializing it, and

  3. returns a pointer to the object. (The pointer has the same value as the address of the allocated memory for the standard new, but this needn't be the case for the array form new[].)

In case the memory allocation fails, an exception of type std::bad_alloc is thrown, no object is constructed and no memory is allocated.

In case the object constructor throws an exception, no object is (obviously) constructed, the memory is automatically released immediately, and the exception is propagated.

Otherwise a dynamically allocated object has been constructed, and the user must manually destroy the object and release the memory, typically by saying delete p;.

The actual allocation and deallocation function can be controlled in C++. If there is nothing else, a global, predefined function ::operator new() is used, but this may be replaced by the user; and if there exists a static member function T::operator new, that one will be used instead.

  • In Java it's fairly similar, only that the return value of new is something that can bind to a Java variable of type T (or a base thereof, such as Object), and you must always have an initializer (so you'd say T x = new T();). The object's lifetime is indeterminate, but guaranteed to be at least as long as any variables still refer to the object, and there is no way to (nor any need to) destroy the object manually. Java has no explicit notion of memory, and you cannot control the interna of the allocation.

Furthermore, C++ allows lots of different forms of new expressions (so-called placement forms). They all create dynamic-storage objects which must be destroyed manually, but they can be fairly arbitrary. To my knowledge Java has no such facilities.


The biggest difference is probably in use: In Java, you use new all the time for everything, and you have to, since it's the one and only way to create (class-type) objects. By contrast, in C++ you should almost never have naked news in user code. C++ has unconstrained variables, and so variables themselves can be objects, and that is how objects are usually used in C++.

Solution 2

I don't know about details in Java, but here is what new and new[] do in C++:

  1. Allocate memory

    When you have an expression new T or new T(args), the compiler determines which function to call for getting memory

    • If the type T has an appropriate member operator new that one is called
    • Otherwise, if the user provided an appropriate global operator new that one is called.

      If operator new cannot allocate the requested memory, then it calls a new handler function, which you can set with set_new_handler. That function may free some space so the allocation can succeed, it may terminate the program, or it may throw an exception of type std::bad_alloc or derived from that. The default new handler just throws std::bad_alloc.

      The same happens for new T[n] except that operator new[] is called for memory allocation.

  2. Construct the object resp. objects in the newly allocated memory.

    For new T(args) the corresponding constructor of the object is called. If the constructor throws an exception, the memory is deallocated 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 POD (i.e. a built-in type or basically a C struct/union) or not. If T is POD, nothing happens, otherwise it is treated like new T().

    For new T[n] it also depends on whether T is POD. Again, PODs are not initialized. For non-PODs the default constructor is in turn called for each of the objects in order. If one object's default constructor throws, no further constructors are called, but the already constructed objects (which doesn't include the one whose constructor just threw) are destructed (i.e. have the destructor called) in reverse order. Then the memory is deallocated with the appropriate operator delete[].

  3. Returns a pointer to the newly created object(s). Note that for new[] the pointer will likely not point to the beginning of the allocated memory because there will likely be some information about the number of allocated objects preceding the constructed objects, which is used by delete[] to figure out how many objects to destruct.

In all cases, the objects live until they are destroyed with delete ptr (for objects allocated with normal new) or delete[] ptr (for objects created with array new T[n]). Unless added with a third-party library, there's no garbage collection in C++.

Note that you also can call operator new and operator delete directly to allocate raw memory. The same is true for operator new[] and operator delete[]. However note that even for those low-level functions you may not mix the calls, e.g. by deallocating memory with operator delete that you allocated with operator new[].

You can also copnstruct an object in allocated memory (no matter how you got that) with the so-called placement new. This is done by giving the pointer to the raw memory as argument to new, like this: new(pMem) T(args). To destruct such an explicitly constructed object, you can call the object's destructor directly, p->~T().

Placement new works by calling an operator new which takes the pointer as additional argument and just returns it. This same mechanism can also be used to provide other information to operator new overloads which take corresponding additional arguments. However while you can define corresponding operator delete, those are only used for cleaning up when an object throws an exception during construction. There's no "placement delete" syntax.

One other use of the placement new syntax which is already provided by C++ is nothrow new. That one takes an additional parameter std::nothrow and differs from normal new only in that it returns a null pointer if allocation fails.

Also note that new is not the only memory management mechanism in C++. On the one hand, there are the C functions malloc and free. While usually operator new and operator new[] just call malloc, this is not guaranteed. Therefore you may not mix those forms (e.g. by calling free on a pointer pointing to memory allocated with operator new). On the other hand, STL containers handle their allocations through allocators, which are objects which manage the allocation/deallocation of objects as well as construction/destruction of objects in containers.

And finally, there are those objects whose lifetime is controlled directly by the language, namely those of static and automatic lifetime. Automatic lifetime objects are allocated by simply defining a variable of the type at local scope. They are automatically created when execution passes that line, and automatically destroyed when execution leaves the scope (including it the scope is left through an exception). Static lifetime objects are define at global/namespace scope or at local scope using the keyword static. They are created at program startup (global/namespace scope) or when their definition line is forst executed (local scope), and they live until the end of the program, when they are automatically destroyed in reverse order of construction.

Generally, automatic or static variables are to be preferred to dynamic allocation (i,e, everything you allocate with new or allocators), because there the compiler cares for proper destruction, unlike dynamic allocation where you have to do that on your own. If you have dynamically allocated objects, it's desirable to have their lifetime managed by automatic/static objects (containers, smart pointers) for the same reason.

Solution 3

In your "statement", I don't think "returns a reference to the first block of allocated memory is quite right. new returns a pointer (to the type of the object allocated). This is subtly different from a reference, although conceptually similar.

Answers to your questions:

  1. In C++ an object stays around in memory (see note) until it is explicitly deleted with delete or delete [] (and you must use the one matching what you allocated with, so a new int[1];, although it is the same amount of memory as new int; can not be deleted with delete (and vice versa, delete [] can't be used for a new int). In Java, the memory gets freed by the garbage collector at some point in the future once there is "no reference to the memory".
  2. Both throw an exception (C++ throws std::bad_alloc, Java something like OutOfMemoryError), but in C++ you can use new(std::nothrow) ..., in which case new returns NULL if there isn't enough memory available to satisfy the call.

Note: It is, as per comment, technically possible to "destroy" the object without freeing it's memory. This is a rather unusual case, and not something you should do unless you are REALLY experienced with C++ and you have a VERY good reason to do so. The typical use-case for this is inside the delete operator corresponding to a placement new (where new is called with an already existing memory address to just perform the construction of the object(s)). Again, placement new is pretty much special use of new, and not something you can expect to see much of in normal C++ code.

Solution 4

You seem to have the operation of new correct in that it allocates and initializes memory.

Once the new completes successfully, you, the programmer, are responsible for deleteing that memory. The best way to make sure that this happens is to never use new directly yourself, instead preferring standard containers and algorithms, and stack-based objects. But if you do need to allocate memory, the C++ idiom is to use a smart pointer like unique_ptr from C++11 or shared_ptr from boost or C++11. That makes sure that the memory is reclaimed properly.

If an allocation fails, the new call will throw an exception after cleaning up any portion of the object that has been constructed prior to the failure. You can use the (nothrow) version of new to return a null pointer instead of throwing an exception, but that places even more burden of cleanup onto the client code.

Share:
10,771
Kunal Balani
Author by

Kunal Balani

If someone knows what exactly I do , please let me know !!

Updated on June 27, 2022

Comments

  • Kunal Balani
    Kunal Balani almost 2 years

    As far as I know, the new operator does the following things: (please correct me if I am wrong.)

    1. Allocates memory, and then returns the reference of the first block of the allocated memory. (The memory is allocated from heap, obviously.)
    2. Initialize the object (calling constructor.)

    Also the operator new[] works in similar fashion except it does this for each and every element in the array.

    Can anybody tell me how both of these operators and different in C++ and Java:

    1. In terms of their life cycle.
    2. What if they fail to allocate memory.
  • Kerrek SB
    Kerrek SB almost 11 years
    More precisely, the object stays alive until its destructor is called. That may be as a result of a delete expression.
  • Mats Petersson
    Mats Petersson almost 11 years
    Ok so we can [or cause a] call [of] the destructor [in some other way], and then call delete later (assuming object was created with new)? I'm not sure how you achieve that [aside from trickery with placement new and other such things, which I didn't go into, and I don't think need to be covered for the OP's purposes, but for completeness should perhaps have been]. (Ok, so if I do T *p = new T; p->~T(); or some such, the object is clearly no longer USABLE, but it's memory is still hanging around... What now?)
  • Kerrek SB
    Kerrek SB almost 11 years
    You can call the destructor directly: p->~T();. That leaves you with unreleased memory, but it's certainly doable. Something like boost::optional does it all the time.
  • Mats Petersson
    Mats Petersson almost 11 years
    Yes, so now we have a lump of memory that is allocated, and unusable [other than placement new]. Seems like a pretty daft thing to do, and I certainly can't see any great use of that for someone who is just starting out in a language.
  • Mats Petersson
    Mats Petersson almost 11 years
    I have updated with a note to say that the object can be destroyed without deleting it, but that it's not a recommended thing to do, and reworded the "alive" bit to say "stays around in memory".
  • Kerrek SB
    Kerrek SB almost 11 years
    What about something like a discriminated union, where you want to be able to store different objects in the same memory? I'm not saying that's common, but it's not a terrible thing to want.
  • M.M
    M.M almost 6 years
    Another aspect of C++ is that in the array new case, if one constructor throws after some constructors have succeeded, then the earlier objects are destructed