This MSDN page mentions that there're nothrow versions of new and delete. nothrow new is quite a known thing - returns null instead of throwing an exception if memory allocation fails. But what is nothrow delete mentioned there?
They are probably referring to the raw memory allocation functions operator new and operator delete.
When you invoke a specific version of placement new-expression (i.e. new-expression with extra parameters; they all are officially referred to as placement forms of new) and the memory allocation function operator new succeeds, but the process fails later for some other reason (the constructor throws), the implementation has to abort the process and automatically release the allocated memory by calling the appropriate version of operator delete. "Appropriate version" of operator delete in this case is the version that has the same set of parameters as the operator new function previously used for memory allocation (except for the very first parameter, of course).
This applies to nothrow version of operator new as well. When you use a nothrow form of new-expression, it calls a nothrow version of operator new and then constructs the object in the allocated memory. If the constructor fails (throws), the implementation of the new-expression releases allocated memory with the help of nothrow version of operator delete. This is basically the only reason for this version of operator delete to exist.
In other words, the nothrow version of operator delete exists for very specific internal purposes. You should not normally want to call it yourself and, maybe, you don't really need to know about its existence. However, it is worth knowing that for the reasons described above, whenever you create your own version of operator new with extra parameters, it is always a good idea to provide a matching version of operator delete with the same set of extra parameters.
Related
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.
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]
I understand that there are 3 general ways to modify the behaviour of new and delete in C++:
Replacing the default new/delete and new[]/delete[]
Overriding or overloading the placement versions (overriding the one with a memory location passed to it, overloading when creating versions which pass other types or numbers of arguments)
Overloading class specific versions.
What are the restrictions for performing these modifications to the behaviour of new/delete?
In particular are there limitations on the signatures that new and delete can be used with?
It makes sense if any replacement versions must have the same signature (otherwise they wouldn't be replacement or would break other code, like the STL for example), but is it permissible to have global placement or class specific versions return smart pointers or some custom handle for example?
First off, don't confuse the new/delete expression with the operator new() function.
The expression is a language construct that performs construction and destruction. The operator is an ordinary function that performs memory (de)allocation.
Only the default operators (operator new(size_t) and operator delete(void *) can be used with the default new and delete expressions. All other forms are summarily called "placement" forms, and for those you can only use new, but you have to destroy objects manually by invoking the destructor. Placement forms are of rather limited and specialised need. By far the most useful placement form is global placement-new, ::new (addr) T, but the behavior of that cannot even be changed (which is presumably why it's the only popular one).
All new operators must return void *. These allocation functions are far more low-level than you might appreciate, so basically you "will know when you need to mess with them".
To repeat: C++ separates the notions of object construction and memory allocation. All you can do is provide alternative implementations for the latter.
When you overload new and delete within a class you are effectively modifying the way the memory is allocated and released for the class, asking for it to give you this control.
This may be done when a class wants to use some kind of pool to allocate its instances, either for optimisation or for tracking purposes.
Restrictions, as with pretty much any operator overload, is the parameter list you may pass, and the behaviour it is expected to adhere to.
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.
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.