Стандарт C++ 11 (1119564), страница 38
Текст из файла (страница 38)
The expression in a noptr-new-declarator shall be of integral type,unscoped enumeration type, or a class type for which a single non-explicit conversion function to integral orunscoped enumeration type exists (12.3). If the expression is of class type, the expression is converted bycalling that conversion function, and the result of the conversion is used in place of the original expression.[ Example: given the definition int n = 42, new float[n][5] is well-formed (because n is the expression ofa noptr-new-declarator), but new float[5][n] is ill-formed (because n is not a constant expression).
— endexample ]7When the value of the expression in a noptr-new-declarator is zero, the allocation function is called toallocate an array with no elements. If the value of that expression is less than zero or such that the sizeof the allocated object would exceed the implementation-defined limit, or if the new-initializer is a bracedinit-list for which the number of initializer-clauses exceeds the number of elements to initialize, no storageis obtained and the new-expression terminates by throwing an exception of a type that would match ahandler (15.3) of type std::bad_array_new_length (18.6.2.2).8A new-expression obtains storage for the object by calling an allocation function (3.7.4.1). If the newexpression terminates by throwing an exception, it may release storage by calling a deallocation function (3.7.4.2). If the allocated type is a non-array type, the allocation function’s name is operator new andthe deallocation function’s name is operator delete.
If the allocated type is an array type, the allocationfunction’s name is operator new[] and the deallocation function’s name is operator delete[]. [ Note: animplementation shall provide default definitions for the global allocation functions (3.7.4, 18.6.1.1, 18.6.1.2).A C++ program can provide alternative definitions of these functions (17.6.4.6) and/or class-specific versions (12.5). — end note ]9If the new-expression begins with a unary :: operator, the allocation function’s name is looked up in theglobal scope. Otherwise, if the allocated type is a class type T or array thereof, the allocation function’sname is looked up in the scope of T.
If this lookup fails to find the name, or if the allocated type is not aclass type, the allocation function’s name is looked up in the global scope.10A new-expression passes the amount of space requested to the allocation function as the first argument oftype std::size_t. That argument shall be no less than the size of the object being created; it may begreater than the size of the object being created only if the object is an array. For arrays of char andunsigned char, the difference between the result of the new-expression and the address returned by theallocation function shall be an integral multiple of the strictest fundamental alignment requirement (3.11) ofany object type whose size is no greater than the size of the array being created. [ Note: Because allocationfunctions are assumed to return pointers to storage that is appropriately aligned for objects of any type withfundamental alignment, this constraint on array allocation overhead permits the common idiom of allocatingcharacter arrays into which objects of other types will later be placed.
— end note ]11The new-placement syntax is used to supply additional arguments to an allocation function. If used, overloadresolution is performed on a function call created by assembling an argument list consisting of the amount ofspace requested (the first argument) and the expressions in the new-placement part of the new-expression (the§ 5.3.4© ISO/IEC 2011 – All rights reserved113ISO/IEC 14882:2011(E)second and succeeding arguments). The first of these arguments has type std::size_t and the remainingarguments have the corresponding types of the expressions in the new-placement.12[ Example:— new T results in a call of operator new(sizeof(T)),— new(2,f) T results in a call of operator new(sizeof(T),2,f),— new T[5] results in a call of operator new[](sizeof(T)*5+x), and— new(2,f) T[5] results in a call of operator new[](sizeof(T)*5+y,2,f).Here, x and y are non-negative unspecified values representing array allocation overhead; the result of thenew-expression will be offset by this amount from the value returned by operator new[].
This overheadmay be applied in all array new-expressions, including those referencing the library function operatornew[](std::size_t, void*) and other placement allocation functions. The amount of overhead may varyfrom one invocation of new to another. — end example ]13[ Note: unless an allocation function is declared with a non-throwing exception-specification (15.4), it indicates failure to allocate storage by throwing a std::bad_alloc exception (Clause 15, 18.6.2.1); it returns anon-null pointer otherwise. If the allocation function is declared with a non-throwing exception-specification,it returns null to indicate failure to allocate storage and a non-null pointer otherwise. — end note ] If theallocation function returns null, initialization shall not be done, the deallocation function shall not be called,and the value of the new-expression shall be null.14[ Note: when the allocation function returns a value other than null, it must be a pointer to a block of storagein which space for the object has been reserved.
The block of storage is assumed to be appropriately alignedand of the requested size. The address of the created object will not necessarily be the same as that of theblock if the object is an array. — end note ]15A new-expression that creates an object of type T initializes that object as follows:— If the new-initializer is omitted, the object is default-initialized (8.5); if no initialization is performed,the object has indeterminate value.— Otherwise, the new-initializer is interpreted according to the initialization rules of 8.5 for directinitialization.16The invocation of the allocation function is indeterminately sequenced with respect to the evaluations ofexpressions in the new-initializer. Initialization of the allocated object is sequenced before the value computation of the new-expression.
It is unspecified whether expressions in the new-initializer are evaluated ifthe allocation function returns the null pointer or exits using an exception.17If the new-expression creates an object or an array of objects of class type, access and ambiguity controlare done for the allocation function, the deallocation function (12.5), and the constructor (12.1). If thenew expression creates an array of objects of class type, access and ambiguity control are done for thedestructor (12.4).18If any part of the object initialization described above76 terminates by throwing an exception and a suitabledeallocation function can be found, the deallocation function is called to free the memory in which the objectwas being constructed, after which the exception continues to propagate in the context of the new-expression.If no unambiguous matching deallocation function can be found, propagating the exception does not causethe object’s memory to be freed.
[ Note: This is appropriate when the called allocation function does notallocate memory; otherwise, it is likely to result in a memory leak. — end note ]76) This may include evaluating a new-initializer and/or calling a constructor.§ 5.3.4114© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)19If the new-expression begins with a unary :: operator, the deallocation function’s name is looked up in theglobal scope. Otherwise, if the allocated type is a class type T or an array thereof, the deallocation function’sname is looked up in the scope of T.
If this lookup fails to find the name, or if the allocated type is not aclass type or array thereof, the deallocation function’s name is looked up in the global scope.20A declaration of a placement deallocation function matches the declaration of a placement allocation functionif it has the same number of parameters and, after parameter transformations (8.3.5), all parameter typesexcept the first are identical.
Any non-placement deallocation function matches a non-placement allocationfunction. If the lookup finds a single matching deallocation function, that function will be called; otherwise,no deallocation function will be called.
If the lookup finds the two-parameter form of a usual deallocationfunction (3.7.4.2) and that function, considered as a placement deallocation function, would have beenselected as a match for the allocation function, the program is ill-formed. [ Example:struct S {// Placement allocation function:static void* operator new(std::size_t, std::size_t);// Usual (non-placement) deallocation function:static void operator delete(void*, std::size_t);};S* p = new (0) S;// ill-formed: non-placement deallocation function matches// placement allocation function— end example ]21If a new-expression calls a deallocation function, it passes the value returned from the allocation functioncall as the first argument of type void*.
If a placement deallocation function is called, it is passed the sameadditional arguments as were passed to the placement allocation function, that is, the same arguments asthose specified with the new-placement syntax. If the implementation is allowed to make a copy of anyargument as part of the call to the allocation function, it is allowed to make a copy (of the same originalvalue) as part of the call to the deallocation function or to reuse the copy made as part of the call to theallocation function.