The c++ programming language by Bjarne Stroustrup - operator new - c++

Section "11.2.4 Overloading new" ends with:
"There is no special syntax for placement of arrays. Nor need there be since arbitrary types can be allocated by placement new. However, an operator delete can be defined for arrays".
If I understand it correctly, what is being said is that for arrays, we use the usual placement new syntax, which would invoke the appropriate operator new[]. But, what I don't understand is the last sentence. What is he trying to say there? Afaik, we can specify both operator new and operator delete for arrays.

There is a special allocator for arrays (operator new[]()) but it is not dependent on a special syntax.
In the following code
new T();
or
new (p) T();
The compiler will generate a call to either operator new(...) or operator new[](...) depending on whether T is an array type. There is no syntactic difference in the new-expression.
(Now, there is a special syntax for a new-expression with a runtime size... but invocation of operator new[]() is not limited to scenarios with a runtime size)
In contrast to new, for delete the same pointer type is compatible with both scalar and array. So you the programmer must tell the compiler which you want via
delete p;
vs
delete [] p;
There is no automatic translation to delete[] based on recognition of an array type.

Related

Are the functionality of _Znwm and _Znam the same in c++?

I'm using llvm lately, and I found that new statements in cpp are translated to _Znam in llvm IR, I know that
new in cpp also call the function _Znwm, and new [] call _Znam, so what's the difference between the functionality of these two functions?
What if I use _Znwm to allocate space for an array?
Example
a = new int*[10];
is compiled as
%2 = call i8* #_Znam(i64 80) #2
_Znwm and _Znam are just mangled names for the functions
operator new(std::size_t)
and
operator new[](std::size_t)
respectively.
An (non-placement) array new expression calls the latter, while a (non-placement) non-array new expression calls the former to allocate memory.
These functions can be replaced by the user, but a default implementation is provided by the standard library. The default implementation of the array version simply calls the non-array version since C++11 and the non-array version allocates memory of the passed size, aligned suitably for all non-overaligned types, in some unspecified way, throwing the exception std::bad_alloc if allocation fails and otherwise returning a non-null pointer to the beginning of the allocated block.
So it behaves similar to std::malloc, except that the latter returns a null pointer if allocation fails, rather than throwing an exception. It is unspecified, but likely, that the default operator new implementation just uses malloc internally to do the allocation.
malloc should not call operator new or operator new[], so I don't know why you think that it would translate to that in IR.
I don't think there is anything LLVM-specific here. Which allocation function is called is specified by the C++ standard. Only the names are mangled in an implementation-defined manner.
Also note that these calls are not all that the new expressions translate to. After calling operator new/operator new[] the new expression will also construct objects in the memory, which may require constructor calls to stores of values.

Storage allocator - what is it?

I know of storage classes in both C and C++ (static, extern, auto, register, C++ also adds mutable and some compiler-specific ones) but I can't figure out what a storage allocator is. I don't think it's referred to memory allocators implementable on STL, what is it in simple terms?
It's whatever is behind operator new and operator delete (not to be confused with the new operator and the delete operator). operator new allocates memory from the free store, and operator delete releases memory previously allocated by operator new for possible reuse. When code does foo *ptr = new foo (new operator), the compiler generates code that calls operator new to get the right number of bytes of storage, then calls the constructor for foo. When code does delete ptr (delete operator) the compiler calls the destructor for foo, then calls operator delete to release the memory.
Note that this is how the term is used in the C++03 standard. In the C++11 standard it is also used to refer to standard allocators.
In the C++ standard, that term is used to refer to the allocator class used by STL-style containers - either std::allocator, or a user-defined custom allocator that meets the requirements given by C++11 17.6.3.5.
However, it's not a formally defined term, and also appears once referring to the implementation of the free store - that is, the dynamic storage allocated by new.
[NOTE: I'm referring to the current (2011) language specification. As noted in the comments, historical versions of the specification apparently only used the term (informally) to refer to the free store]

Memory allocation operators and expressions

In C++, is 'new' an operator or an expression or some kind of keyword? a similar question that comes in mind is, should i call '=' an operator or expression?
C++ separates the notion of memory allocation and object lifetime. This is a new feature compared to C, since in C an object was equivalent to its memory representation (which is called "POD" in C++).
An object begins its life when a constructor has completed, and its life ends when the destructor has completed. For an object of dynamic storage duration, the life cycle thus consists of four key milestones:
Memory allocation.
Object construction.
Object destruction.
Memory deallocation.
The standard way in C++ to allocate memory dynamically is with the global ::operator new(), and deallocation with ::operator delete(). However, to construct an object there is only one method: A new expression:
T * p = new T;
This most common form of the new expression does allocation and construction in one step. It is equivalent to the broken down version:
void * addr = ::operator new(sizeof(T));
T * p = new (addr) T; // placement-new
Similarly, the delete expression delete p; first calls the destructor and then releases memory. It is equivalent to this:
p->~T();
::operator delete(addr);
Thus, the default new and delete expressions perform memory allocation and object construction in one wash. All other forms of the new expression, collectively called "placement new", call a corresponding placement-new operator to allocate memory before constructing the object. However, there is no matching "placement delete expression", and all dynamic objects created with placement-new have to be destroyed manually with p->~T();.
In summary, it is very important to distinguish the new expression from the operator new. This is really at the heart of memory management in C++.
It's all of those.
2.13 Table 4 explicitly lists new as a keyword.
5.3.4 Introduces the new-expression. This is an expression such as new int(5) which uses the new keyword, a type and an initial value.
5.3.4/8 Then states that operator new is called to allocate memory for the object created by the new-expression
= works quite the same. Each class has an operator= (unless explicitly deleted), which is used in assignment expressions. We usually call a=5; just an assignment, even when it's technically "an expression statement containing an assignment expression."
new is operator. You can overload it and write your own version of it. Also I think that = is operator. Expression is more complex thing which consist of operators, variables, function calls etc. And please try to get C++ language standard. It must describe all things you mentioned.

Is C++ code allowed to call `::operator new()` directly?

According to C++ Standard paragraph 3.7.3/1 objects should be dynamically created with new expression and the C++ runtime should provide an allocation function ::operator new().
Once in a while it is necessary to call ::operator new() directly.
Does the C++ Standard allow such calls to ::operator new() function or is this (and related) function for internal use only?
It's perfectly acceptable to call operator new and operator delete directly; they are a part of the global namespace and act like a C++-ier version of malloc and free that interact with set_new_handler and the bad_alloc exceptions a bit nicer. The C++ ISO standard even contains a few examples of this. For example, §13.5/4 has this example:
Operator functions are usually not called directly; instead they are invoked to evaluate the operators they implement (13.5.1 - 13.5.7). They can be explicitly called, however, using the operator-function-id as the name of the function in the function call syntax (5.2.2). [Example:
complex z = a.operator+(b); // complex z = a+b;
void* p = operator new(sizeof(int)*n);
—end example]
Yes, it is allowed to call the global operator new function directly – though it's not as often required as you might believe. You must match allocation and deallocation functions, but if you have full control over both, then you can always use new[] and delete[] with char. However, that would be a new-expression and delete-expression, so you are only "required" to use the global functions themselves if you need a function pointer. (You would have to wrap the new-expression to get a function pointer, otherwise.)
If you replace these global functions so that new and new[] use different heaps, for example, then you might also want to explicitly use ::operator new, but this is rare.

operator new and new operator, which can't be overloaded?

It seems both can be overloaded, but somebody said not.....
What's the case?
It seems you are making the distinction between the handling of new-expressions and allocation functions. new-expressions call constructors in addition for class types and is responsible for looking up allocation functions (so it is built into the compiler) and calling them. You can't change that behavior. What you can change is the behavior of allocation functions. Their name is operator new and they are found and used by new-expressions to allocate memory.
See Plain new, new[], delete and delete[] in a nutshell.
You can overload all four of, new, new[], delete, and delete[]. See section 13.5 of the standard.
You can overlload new operator but you cannot define new operators(like ^ or ++).
If it is not what you meant please clarify.