26

I understand the benefits of using new against malloc in C++. But for specific cases such as primitive data types (non array) - int, float etc., is it faster to use malloc than new?

Although, it is always advisable to use new even for primitives, if we are allocating an array so that we can use delete[].

But for non-array allocation, I think there wouldn't be any constructor call for int? Since, new operator allocates memory, checks if it's allocated and then calls the constructor. But just for primitives non-array heap allocation, is it better to use malloc than new?

Please advise.

Azeem
  • 7,094
  • 4
  • 19
  • 32
Rajeev Mehta
  • 599
  • 8
  • 17
  • 2
    _" is it faster to use malloc than new?"_ Probably not. Even given that `new`would be implemented using `malloc` internally it likely that these calls are simply inlined. – πάντα ῥεῖ Jun 16 '17 at 11:40
  • 20
    Use neither. Use `std::unique_ptr` for a fixed sized dynamic array or `std::vector` for a variable sized dynamic array. – NathanOliver Jun 16 '17 at 11:41
  • 16
    Would strongly advice against using either. – Richard Critten Jun 16 '17 at 11:41
  • @πάνταῥεῖ Doesn't `new` have to initialize the value and `malloc` doesn't? Wouldn't that make `malloc` likely to, at least sometimes, be faster? – David Schwartz Jun 17 '17 at 04:00
  • @david Hmm, fair point. – πάντα ῥεῖ Jun 17 '17 at 08:58
  • 1
    While others have pointed out that it is almost always better to use neither `new` nor `malloc`, it is still an interesting question if `malloc` is sometimes faster than `new`. Why not benchmark it? – John Coleman Jun 17 '17 at 14:41
  • 1
    @NathanOliver is there any particular benefit to `std::unique_ptr` over `std::vector` for both cases? – Caleth Oct 02 '17 at 16:10
  • @Caleth Not really. In fact `std::unique_ptr` will initialize all elements where `std::vector` does not unless you tell it to. The only reason I suggested `std::unique_ptr` was because it expresses that it is a fixed sized dynamically allocated buffer. I use `vector` by default and until the profiler tells me I need to look for something else. – NathanOliver Oct 02 '17 at 16:13
  • @NathanOliver Why would you use `std::unique_ptr`, when you have `std::array`? – Clearer Mar 29 '18 at 12:36
  • 1
    @Clearer If you don't know the size until run time then you can't use `std::array` – NathanOliver Mar 29 '18 at 12:40

5 Answers5

86

Never use malloc in C++. Never use new unless you are implementing a low-level memory management primitive.

The recommendation is:

  • Ask yourself: "do I need dynamic memory allocation?". A lot of times you might not need it - prefer values to pointers and try to use the stack.

  • If you do need dynamic memory allocation, ask yourself "who will own the allocated memory/object?".

    • If you only need a single owner (which is very likely), you should use std::unique_ptr. It is a zero cost abstraction over new/delete. (A different deallocator can be specified.)

    • If you need shared ownership, you should use std::shared_ptr. This is not a zero cost abstraction, as it uses atomic operations and an extra "control block" to keep track of all the owners.


If you are dealing with arrays in particular, the Standard Library provides two powerful and safe abstractions that do not require any manual memory management:

std::array and std::vector should cover 99% of your "array needs".


One more important thing: the Standard Library provides the std::make_unique and std::make_shared which should always be used to create smart pointer instances. There are a few good reasons:

  • Shorter - no need to repeat the T (e.g. std::unique_ptr<T>{new T}), no need to use new.

  • More exception safe. They prevent a potential memory leak caused by the lack of a well-defined order of evaluation in function calls. E.g.

    f(std::shared_ptr<int>(new int(42)), g())
    

    Could be evaluated in this order:

    1. new int(42)
    2. g()
    3. ...

    If g() throws, the int is leaked.

  • More efficient (in terms of run-time speed). This only applies to std::make_shared - using it instead of std::shared_ptr directly allows the implementation to perform a single allocation both for the object and for the control block.

You can find more information in this question.

Vittorio Romeo
  • 82,972
  • 25
  • 221
  • 369
  • 3
    Might want to note that "more efficient" is in terms of speed, not necessarily memory. In particular, a `weak_ptr` would hold on to the entire memory block containing the refcount, and for a large object that might linger, that might not be so great. – user541686 Jun 17 '17 at 03:34
  • 1
    I fail to see how your, even elaborated, answer has anything to do with the question. For instance, it as asked if for int/float arrays, which one is faster to use, new or malloc. – Pierre May 24 '19 at 11:45
27

It can still be necessary to use malloc and free in C++ when you are interacting with APIs specified using plain C, because it is not guaranteed to be safe to use free to deallocate memory allocated with operator new (which is ultimately what all of the managed memory classes use), nor to use operator delete to deallocate memory allocated with malloc.

A typical example is POSIX getline (not to be confused with std::getline): it takes a pointer to a char * variable; that variable must point to a block of memory allocated with malloc (or it can be NULL, in which case getline will call malloc for you); when you are done calling getline you are expected to call free on that variable.

Similarly, if you are writing a library, it can make sense to use C++ internally but define an extern "C" API for your external callers, because that gives you better binary interface stability and cross-language interoperability. And if you return heap-allocated POD objects to your callers, you might want to let them deallocate those objects with free; they can't necessarily use delete, and making them call YourLibraryFree when there are no destructor-type operations needed is unergonomic.

It can also still be necessary to use malloc when implementing resizable container objects, because there is no equivalent of realloc for operator new.

But as the other answers say, when you don't have this kind of interface constraint tying your hands, use one of the managed memory classes instead.

zwol
  • 121,956
  • 33
  • 219
  • 328
  • Why not simply do `auto ptr = std::make_unique()` and later `return ptr.release()`? Yes, it is more code, but if there's logic in between, it works nicely. – Justin Jun 17 '17 at 07:25
  • 7
    Because there's no guarantee that memory allocated by `std::make_unique()` is safe to deallocate using `free()` – D. Jurcau Jun 17 '17 at 07:31
  • Well constructed API would usually require you to provide a deallocator (as a function pointer), but alas some still don't. – spectras Jun 17 '17 at 14:59
  • 1
    anyway, you can't use realloc for implementing resizable container objects, because you can't know beforehand if your data will stay at the same address. After the call, if realloc did move your data, you're screwed because you did not call objects move constructor. You need to allocate-move-free, or call OS specific API such as HeapReAlloc with HEAP_REALLOC_IN_PLACE_ONLY flag. – ThreeStarProgrammer57 Jun 22 '17 at 16:27
  • @ThreeStarProgrammer57 Container resize is specifically allowed to invalidate iterators and other forms of external pointers into the container. If you write objects that care about their own addresses, you have only yourself to blame. – zwol Jun 24 '17 at 23:32
  • 2
    @zwol the problem is not external iterators or pointers. If realloc cannot realloc in place, it performs a raw memcpy to the new memory. In C++, this is wrong. Moving (or copying) an object requires calling its move (or copy) constructor. raw memcpy may work with some objects, but for any general purpose container it is not correct. – ThreeStarProgrammer57 Jun 25 '17 at 11:50
  • @ThreeStarProgrammer57 Objects that can't be _moved_ (not necessarily copied) with raw `memcpy` are firmly in "don't do that then" territory. – zwol Jun 25 '17 at 15:49
  • @zwol `template class SomeContainer` is off limits then – Caleth Oct 02 '17 at 16:03
8

It's always better to use new. If you use malloc you still have to check manually if space is allocated.

In modern c++ you can use smart pointers. With make_unique and make_shared you never call new explicitly. std::unique_ptr is not bigger than the underlying pointer and the overhead of using it is minimal.

Petar Velev
  • 2,213
  • 10
  • 21
6

The answer to "should I use new or malloc" is single responsibillity rule.

Resource management should be done by a type that has that as its sole purpose.
Those classes already exists, such as unique_ptr, vector etc.

Directly using either malloc or new is a cardinal sin.

JDługosz
  • 4,053
  • 2
  • 20
  • 39
sp2danny
  • 6,824
  • 2
  • 27
  • 49
3

zwol's answer already gives the correct correctness answer: Use malloc()/free() when interacting with C interfaces only.
I'm not going to repeat those details, I'm going to answer the performance question.

The truth is, that the performance of malloc() and new can, and does differ. When you perform an allocation with new, the memory will generally be allocated via call to the global operator new() function, which is distinct from malloc(). It is trivial to implement operator new() by calling through to malloc(), but this is not necessarily done.

As a matter of fact, I've seen a system where an operator new() that calls through to malloc() would outperform the standard implementation of operator new() by roughly 100 CPU cycles per call. That's definitely a measurable difference, and a clear indication that the standard implementation does something very different from malloc().

So, if you are worried about performance, there is three things to do:

  1. Measure your performance.

  2. Write replacement implementations for the global operator new() function and its friends.

  3. Measure your performance and compare.

The gains/losses may or may not be significant.

cmaster - reinstate monica
  • 33,875
  • 7
  • 50
  • 100