1

I know both functions accepts size_t number. For malloc that number is raw bytes and for the allocate it is rahter n*sizeof(T) of that type. So does allocate call internally malloc? Also, from cpp reference about allocate:

Allocates n * sizeof(T) bytes of uninitialized storage by calling ::operator new(std::size_t)

It calls new operator. But as far as I know, the new operator not only allocates memory, but also initialize it with the constructor for the type, from In what cases do I use malloc and/or new?:

The new keyword is the C++ way of doing it, and it will ensure that your type will have its constructor called

But the reference claim it will return uninitialized, only allocated memory, just as malloc does. So the question is also a little bit about new, does it also initialize (by calling default constructor or value-initilize for primitive types) or not? And does allocate calls malloc by its implementation or how does it requests OS for block of raw memory/

milanHrabos
  • 2,010
  • 3
  • 11
  • 45

1 Answers1

0

Your quote of std::allocator<T>::allocate:

Allocates n * sizeof(T) bytes of uninitialized storage by calling ::operator new(std::size_t) or ::operator new(std::size_t, std::align_val_t)

Does not refer to the new expression that creates and initializes objects. But to the operator new which is called by the c++ runtime to allocate memory in case of the new expression.

The default operator new might internally look like:

void* operator new(std::size_t sz) {
    void *ptr = std::malloc(sz);
    if (ptr)
        return ptr;
    else
        throw std::bad_alloc{};
}

But that's implementation-dependent, it could internally use any method provided by the OS to allocate memory. For embedded systems, it might even be a function that manages preallocated memory.

And does allocate calls malloc by its implementation or how does it requests OS for block of raw memory

That can't be said as it is implementation-dependent, but for the common implementations, you probably could assume that malloc and allocate internally use the same system calls, but if allocate das this directly or using in indirection over malloc is also implementation dependent.

t.niese
  • 39,256
  • 9
  • 74
  • 101
  • I did not know, there is difference between new-expression and new-operator. I though *I am* using the new operator in my c++ code – milanHrabos Aug 08 '20 at 09:44
  • @milanHrabos It's confusing but the difference is between the new operator (e.g. `new int[10]`) and operator new (e.g. `operator new(10*sizeof(int))`). The former is used a lot, the latter is quite specialist. – john Aug 08 '20 at 09:56
  • @milanHrabos the `operator new` is normally only used by the runtime internally and not directly in the code. The idea behind it is, to give the developer control over how the memory is allocated, by providing an own implementation of it. But this is rarely needed, mostly only in the field of embedded systems, where memory is really limited. – t.niese Aug 08 '20 at 10:01
  • @t.niese so that means,that the internal operator new as in your example `operator new(10*sizeof(int))` is the same as old-trusty `malloc` right? Why does even the `operator new` exists? What is its advantage to make new function, instead of using the malloc? – milanHrabos Aug 08 '20 at 11:23
  • @milanHrabos no, what I said is that it is likely that the default `operator new` one uses `malloc` internally. `new Foo()` will call `operator new(sizeof(Foo))` and then call the constructor for `Foo` on the allocated space. Having `operator new` allows you to redefine how memory is allocated. You could allocate a large chunk of memory manually using `malloc` and manually manage that memory chunk in `operator new`. Or if the OS provides different ways for memory allocation, that you could choose which one you want to use. – t.niese Aug 08 '20 at 13:55
  • @milanHrabos It just allows you to have the freedom to control how memory is allocated for `new`. A **hypothetical** example could be the flowing: An OS provides two kinds of memories, error-corrected but slower, and none error corrected but faster memory, by default it might use the none error corrected, but provides an API to choose the error corrected one. Having `operator new` allows you to choose which one to use (either globally, per class or per translation unit). – t.niese Aug 08 '20 at 13:59