668 lines
33 KiB
Markdown
668 lines
33 KiB
Markdown
[expr.new]
|
||
|
||
# 7 Expressions [[expr]](./#expr)
|
||
|
||
## 7.6 Compound expressions [[expr.compound]](expr.compound#expr.new)
|
||
|
||
### 7.6.2 Unary expressions [[expr.unary]](expr.unary#expr.new)
|
||
|
||
#### 7.6.2.8 New [expr.new]
|
||
|
||
[1](#1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5752)
|
||
|
||
The [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") attempts to create an object of the[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") or [*new-type-id*](#nt:new-type-id "7.6.2.8 New [expr.new]") ([[dcl.name]](dcl.name "9.3.2 Type names")) to which
|
||
it is applied[.](#1.sentence-1)
|
||
|
||
The type of that object is the [*allocated type*](#def:type,allocated "7.6.2.8 New [expr.new]")[.](#1.sentence-2)
|
||
|
||
This type shall be a complete object type ([[basic.types.general]](basic.types.general#term.incomplete.type "6.9.1 General")),
|
||
but not an abstract class type ([[class.abstract]](class.abstract "11.7.4 Abstract classes")) or array
|
||
thereof ([[intro.object]](intro.object "6.8.2 Object model"))[.](#1.sentence-3)
|
||
|
||
[*Note [1](#note-1)*:
|
||
|
||
Because references are not objects, references cannot be created by[*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]")*s*[.](#1.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[*Note [2](#note-2)*:
|
||
|
||
The [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") can be a cv-qualified type, in which case the
|
||
object created by the [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") has a cv-qualified type[.](#1.sentence-5)
|
||
|
||
â *end note*]
|
||
|
||
[new-expression:](#nt:new-expression "7.6.2.8 New [expr.new]")
|
||
::opt new [*new-placement*](#nt:new-placement "7.6.2.8 New [expr.new]")opt [*new-type-id*](#nt:new-type-id "7.6.2.8 New [expr.new]") [*new-initializer*](#nt:new-initializer "7.6.2.8 New [expr.new]")opt
|
||
::opt new [*new-placement*](#nt:new-placement "7.6.2.8 New [expr.new]")opt ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ) [*new-initializer*](#nt:new-initializer "7.6.2.8 New [expr.new]")opt
|
||
|
||
[new-placement:](#nt:new-placement "7.6.2.8 New [expr.new]")
|
||
( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") )
|
||
|
||
[new-type-id:](#nt:new-type-id "7.6.2.8 New [expr.new]")
|
||
[*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") [*new-declarator*](#nt:new-declarator "7.6.2.8 New [expr.new]")opt
|
||
|
||
[new-declarator:](#nt:new-declarator "7.6.2.8 New [expr.new]")
|
||
[*ptr-operator*](dcl.decl.general#nt:ptr-operator "9.3.1 General [dcl.decl.general]") [*new-declarator*](#nt:new-declarator "7.6.2.8 New [expr.new]")opt
|
||
[*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8 New [expr.new]")
|
||
|
||
[noptr-new-declarator:](#nt:noptr-new-declarator "7.6.2.8 New [expr.new]")
|
||
[ [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]")opt ] [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||
[*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8 New [expr.new]") [ [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") ] [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||
|
||
[new-initializer:](#nt:new-initializer "7.6.2.8 New [expr.new]")
|
||
( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||
[*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||
|
||
[2](#2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5813)
|
||
|
||
If a [placeholder type](dcl.spec.auto "9.2.9.7 Placeholder type specifiers [dcl.spec.auto]") or
|
||
a placeholder for a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8 Deduced class template specialization types"))
|
||
appears in the[*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") of a [*new-type-id*](#nt:new-type-id "7.6.2.8 New [expr.new]") or[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") of a [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]"),
|
||
the allocated type is deduced as follows:
|
||
Let*init* be the [*new-initializer*](#nt:new-initializer "7.6.2.8 New [expr.new]"), if any,
|
||
andT be the [*new-type-id*](#nt:new-type-id "7.6.2.8 New [expr.new]") or [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") of
|
||
the [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]"), then the allocated type is the type
|
||
deduced for the variable x in the invented
|
||
declaration ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers")):T x *init* ;
|
||
|
||
[*Example [1](#example-1)*: new auto(1); // allocated type is intauto x = new auto('a'); // allocated type is char, x is of type char*template<class T> struct A { A(T, T); };auto y = new A{1, 2}; // allocated type is A<int> â *end example*]
|
||
|
||
[3](#3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5841)
|
||
|
||
The [*new-type-id*](#nt:new-type-id "7.6.2.8 New [expr.new]") in a [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") is the longest
|
||
possible sequence of [*new-declarator*](#nt:new-declarator "7.6.2.8 New [expr.new]")*s*[.](#3.sentence-1)
|
||
|
||
[*Note [3](#note-3)*:
|
||
|
||
This prevents ambiguities between the declarator operators &, &&,*, and [] and their expression counterparts[.](#3.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [2](#example-2)*: new int * i; // syntax error: parsed as (new int*) i, not as (new int)*i
|
||
|
||
The * is the pointer declarator and not the multiplication
|
||
operator[.](#3.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
[4](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5856)
|
||
|
||
[*Note [4](#note-4)*:
|
||
|
||
Parentheses in a [*new-type-id*](#nt:new-type-id "7.6.2.8 New [expr.new]") of a [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") can have surprising effects[.](#4.sentence-1)
|
||
|
||
[*Example [3](#example-3)*:
|
||
|
||
new int(*[10])(); // error is ill-formed because the binding is(new int) (*[10])(); // error
|
||
|
||
Instead, the explicitly parenthesized version of the new operator can be used to create objects of compound
|
||
types ([[basic.compound]](basic.compound "6.9.4 Compound types")):
|
||
|
||
new (int (*[10])()); allocates an array of 10 pointers to functions (taking no
|
||
argument and returning int)[.](#4.sentence-4)
|
||
|
||
â *end example*]
|
||
|
||
â *end note*]
|
||
|
||
[5](#5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5882)
|
||
|
||
The [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") in a [*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8 New [expr.new]") appertains
|
||
to the associated array type[.](#5.sentence-1)
|
||
|
||
[6](#6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5886)
|
||
|
||
Every [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") in a[*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8 New [expr.new]") shall be a converted constant
|
||
expression ([[expr.const]](expr.const "7.7 Constant expressions")) of type std::size_t and
|
||
its value shall be greater than zero[.](#6.sentence-1)
|
||
|
||
[*Example [4](#example-4)*:
|
||
|
||
Given the definition int n = 42,new float[n][5] is well-formed (because n is the[*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") of a [*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8 New [expr.new]")), butnew float[5][n] is ill-formed (because n is not a
|
||
constant expression)[.](#6.sentence-2)
|
||
|
||
Furthermore,new float[0] is well-formed
|
||
(because 0 is the [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") of a [*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8 New [expr.new]"),
|
||
where a value of zero results in the allocation of an array with no elements),
|
||
but new float[n][0] is ill-formed
|
||
(because 0 is the [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") of a [*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8 New [expr.new]"),
|
||
where only values greater than zero are allowed)[.](#6.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
[7](#7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5908)
|
||
|
||
If the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") or [*new-type-id*](#nt:new-type-id "7.6.2.8 New [expr.new]") denotes an array type of unknown bound ([[dcl.array]](dcl.array "9.3.4.5 Arrays")),
|
||
the [*new-initializer*](#nt:new-initializer "7.6.2.8 New [expr.new]") shall not be omitted;
|
||
the allocated object is an array with n elements,
|
||
where n is determined from the number of initial elements
|
||
supplied in
|
||
the [*new-initializer*](#nt:new-initializer "7.6.2.8 New [expr.new]") ([[dcl.init.aggr]](dcl.init.aggr "9.5.2 Aggregates"), [[dcl.init.string]](dcl.init.string "9.5.3 Character arrays"))[.](#7.sentence-1)
|
||
|
||
[8](#8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5917)
|
||
|
||
If the [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") in a [*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8 New [expr.new]") is present, it is implicitly converted to std::size_t[.](#8.sentence-1)
|
||
|
||
The value of the [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is invalid if
|
||
|
||
- [(8.1)](#8.1)
|
||
|
||
the expression is of non-class type and its value before converting tostd::size_t is less than zero;
|
||
|
||
- [(8.2)](#8.2)
|
||
|
||
the expression is of class type and its value before application of the second
|
||
standard conversion ([[over.ics.user]](over.ics.user "12.2.4.2.3 User-defined conversion sequences"))[59](#footnote-59 "If the conversion function returns a signed integer type, the second standard conversion converts to the unsigned type std::size_t and thus thwarts any attempt to detect a negative value afterwards.") is less than zero;
|
||
|
||
- [(8.3)](#8.3)
|
||
|
||
its value is such that the size of the allocated object would exceed theimplementation-defined [limit](implimits "Annex B (informative) Implementation quantities [implimits]"); or
|
||
|
||
- [(8.4)](#8.4)
|
||
|
||
the [*new-initializer*](#nt:new-initializer "7.6.2.8 New [expr.new]") is a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]") and the
|
||
number of array elements for which initializers are provided (including the
|
||
terminating '\0' in a [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") ([[lex.string]](lex.string "5.13.5 String literals"))) exceeds the
|
||
number of elements to initialize[.](#8.sentence-2)
|
||
|
||
If the value of the [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is invalid after converting to std::size_t:
|
||
|
||
- [(8.5)](#8.5)
|
||
|
||
if the [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is a potentially-evaluated core constant expression,
|
||
the program is ill-formed;
|
||
|
||
- [(8.6)](#8.6)
|
||
|
||
otherwise, an allocation function is not called; instead
|
||
* [(8.6.1)](#8.6.1)
|
||
|
||
if the allocation function that would have been called
|
||
has a non-throwing exception specification ([[except.spec]](except.spec "14.5 Exception specifications")),
|
||
the value of the [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") is the null pointer value of the required result type;
|
||
|
||
* [(8.6.2)](#8.6.2)
|
||
|
||
otherwise, the [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") terminates by throwing an
|
||
exception of a type that would match a handler ([[except.handle]](except.handle "14.4 Handling an exception")) of type[std::bad_array_new_length](new.badlength "17.6.4.2 Class bad_array_new_length [new.badlength]")[.](#8.sentence-3)
|
||
|
||
When the value of the [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is zero, the allocation
|
||
function is called to allocate an array with no elements[.](#8.sentence-4)
|
||
|
||
[9](#9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5972)
|
||
|
||
If the allocated type is an array,
|
||
the [*new-initializer*](#nt:new-initializer "7.6.2.8 New [expr.new]") is a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]"), and
|
||
the [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is potentially-evaluated and not a core constant expression,
|
||
the semantic constraints of copy-initializing a hypothetical element of
|
||
the array from an empty initializer list
|
||
are checked ([[dcl.init.list]](dcl.init.list "9.5.5 List-initialization"))[.](#9.sentence-1)
|
||
|
||
[*Note [5](#note-5)*:
|
||
|
||
The array can contain more elements than there are
|
||
elements in the [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]"),
|
||
requiring initialization of the remainder of the array elements from
|
||
an empty initializer list[.](#9.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[10](#10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5987)
|
||
|
||
Objects created by a [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") have dynamic storage
|
||
duration ([[basic.stc.dynamic]](basic.stc.dynamic "6.8.6.5 Dynamic storage duration"))[.](#10.sentence-1)
|
||
|
||
[*Note [6](#note-6)*:
|
||
|
||
The lifetime of such an object is not necessarily restricted to the
|
||
scope in which it is created[.](#10.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[11](#11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L5997)
|
||
|
||
When the allocated type is âarray of N Tâ
|
||
(that is, the [*noptr-new-declarator*](#nt:noptr-new-declarator "7.6.2.8 New [expr.new]") syntax is used or the[*new-type-id*](#nt:new-type-id "7.6.2.8 New [expr.new]") or [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") denotes an array type),
|
||
the [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") yields a prvalue of type âpointer to Tâ
|
||
that points to the initial element (if any) of the array[.](#11.sentence-1)
|
||
|
||
Otherwise, let T be the allocated type;
|
||
the [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") is a prvalue of type âpointer to Tâ
|
||
that points to the object created[.](#11.sentence-2)
|
||
|
||
[*Note [7](#note-7)*:
|
||
|
||
Both new int and new int[10] have type int* and
|
||
the type of new int[i][10] is int (*)[10][.](#11.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[12](#12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6013)
|
||
|
||
A [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") may obtain storage for the object by calling an
|
||
allocation function ([[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2 Allocation functions"))[.](#12.sentence-1)
|
||
|
||
If
|
||
the [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") terminates by throwing an exception, it
|
||
may release storage by calling a [deallocation
|
||
function](basic.stc.dynamic.deallocation "6.8.6.5.3 Deallocation functions [basic.stc.dynamic.deallocation]")[.](#12.sentence-2)
|
||
|
||
If the allocated type
|
||
is a non-array type, the allocation function's name isoperator new and the deallocation function's name isoperator delete[.](#12.sentence-3)
|
||
|
||
If the allocated type is an array type, the
|
||
allocation function's name isoperator new[] and the deallocation function's name isoperator delete[][.](#12.sentence-4)
|
||
|
||
[*Note [8](#note-8)*:
|
||
|
||
An implementation is expected to provide default definitions for the global
|
||
allocation
|
||
functions ([[basic.stc.dynamic]](basic.stc.dynamic "6.8.6.5 Dynamic storage duration"), [[new.delete.single]](new.delete.single "17.6.3.2 Single-object forms"), [[new.delete.array]](new.delete.array "17.6.3.3 Array forms"))[.](#12.sentence-5)
|
||
|
||
A C++ program can provide alternative definitions of
|
||
these functions ([[replacement.functions]](replacement.functions "16.4.5.6 Replacement functions")) and/or class-specific
|
||
versions ([[class.free]](class.free "11.4.11 Allocation and deallocation functions"))[.](#12.sentence-6)
|
||
|
||
The set of allocation and deallocation functions that can be called
|
||
by a [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") can include functions that do not perform allocation or deallocation;
|
||
for example, see [[new.delete.placement]](new.delete.placement "17.6.3.4 Non-allocating forms")[.](#12.sentence-7)
|
||
|
||
â *end note*]
|
||
|
||
[13](#13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6043)
|
||
|
||
If the [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") does not begin with a unary :: operator and
|
||
the allocated type is a class type T or array thereof,
|
||
a search is performed for the allocation function's name in the scope
|
||
of T ([[class.member.lookup]](class.member.lookup "6.5.2 Member name lookup"))[.](#13.sentence-1)
|
||
|
||
Otherwise, or if nothing is found,
|
||
the allocation function's name is looked up by
|
||
searching for it in the global scope[.](#13.sentence-2)
|
||
|
||
[14](#14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6054)
|
||
|
||
An implementation is allowed to omit a call to a replaceable global allocation
|
||
function ([[new.delete.single]](new.delete.single "17.6.3.2 Single-object forms"), [[new.delete.array]](new.delete.array "17.6.3.3 Array forms"))[.](#14.sentence-1)
|
||
|
||
When it does so,
|
||
the storage is instead provided by the implementation or provided by extending
|
||
the allocation of another [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]")[.](#14.sentence-2)
|
||
|
||
[15](#15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6060)
|
||
|
||
During an evaluation of a constant expression,
|
||
a call to a replaceable allocation function is always omitted ([[expr.const]](expr.const "7.7 Constant expressions"))[.](#15.sentence-1)
|
||
|
||
[16](#16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6064)
|
||
|
||
The implementation may
|
||
extend the allocation of a [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") e1 to provide
|
||
storage for a [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") e2 if the
|
||
following would be true were the allocation not extended:
|
||
|
||
- [(16.1)](#16.1)
|
||
|
||
the evaluation of e1 is sequenced before the evaluation ofe2, and
|
||
|
||
- [(16.2)](#16.2)
|
||
|
||
e2 is evaluated whenever e1 obtains storage, and
|
||
|
||
- [(16.3)](#16.3)
|
||
|
||
both e1 and e2 invoke the same replaceable global
|
||
allocation function, and
|
||
|
||
- [(16.4)](#16.4)
|
||
|
||
if the allocation function invoked by e1 and e2 is
|
||
throwing, any exceptions thrown in the evaluation of either e1 ore2 would be first caught in the same handler, and
|
||
|
||
- [(16.5)](#16.5)
|
||
|
||
the pointer values produced by e1 and e2 are operands to
|
||
evaluated [*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9 Delete [expr.delete]")*s*, and
|
||
|
||
- [(16.6)](#16.6)
|
||
|
||
the evaluation of e2 is sequenced before the evaluation of the[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9 Delete [expr.delete]") whose operand is the pointer value produced
|
||
by e1[.](#16.sentence-1)
|
||
|
||
[*Example [5](#example-5)*: void can_merge(int x) {// These allocations are safe for merging: std::unique_ptr<char[]> a{new (std::nothrow) char[8]};
|
||
std::unique_ptr<char[]> b{new (std::nothrow) char[8]};
|
||
std::unique_ptr<char[]> c{new (std::nothrow) char[x]};
|
||
|
||
g(a.get(), b.get(), c.get());}void cannot_merge(int x) { std::unique_ptr<char[]> a{new char[8]}; try {// Merging this allocation would change its catch handler. std::unique_ptr<char[]> b{new char[x]}; } catch (const std::bad_alloc& e) { std::cerr << "Allocation failed: " << e.what() << std::endl; throw; }} â *end example*]
|
||
|
||
[17](#17)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6114)
|
||
|
||
When a [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") calls an allocation function and that
|
||
allocation has not been extended, the[*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") passes the amount of space requested to the
|
||
allocation function as the first argument of typestd::size_t[.](#17.sentence-1)
|
||
|
||
That argument shall be no less than the size
|
||
of the object being created; it may be greater than the size of the
|
||
object being created only if the object is an array and
|
||
the allocation function is not a non-allocating form ([[new.delete.placement]](new.delete.placement "17.6.3.4 Non-allocating forms"))[.](#17.sentence-2)
|
||
|
||
For arrays ofchar, unsigned char, and std::byte,
|
||
the difference between the
|
||
result of the [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") and the address returned by the
|
||
allocation function shall be an integral multiple of the
|
||
strictest fundamental[alignment requirement](basic.align "6.8.3 Alignment [basic.align]") of any object type whose size
|
||
is no greater than the size of the array being created[.](#17.sentence-3)
|
||
|
||
[*Note [9](#note-9)*:
|
||
|
||
Because allocation functions are assumed to return pointers to storage
|
||
that is appropriately aligned for objects of any type
|
||
with fundamental alignment, this constraint
|
||
on array allocation overhead permits the common idiom of allocating
|
||
character arrays into which objects of other types will later be placed[.](#17.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[18](#18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6140)
|
||
|
||
When a [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") calls an allocation function and that
|
||
allocation has been extended, the size argument to the allocation call shall
|
||
be no greater than the sum of the sizes for the omitted calls as specified
|
||
above, plus the size for the extended call had it not been extended, plus any
|
||
padding necessary to align the allocated objects within the allocated memory[.](#18.sentence-1)
|
||
|
||
[19](#19)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6147)
|
||
|
||
The [*new-placement*](#nt:new-placement "7.6.2.8 New [expr.new]") syntax is used to supply additional
|
||
arguments to an allocation function; such an expression is called
|
||
a [*placement* ](#def:new-expression,placement "7.6.2.8 New [expr.new]")*[*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]")*[.](#19.sentence-1)
|
||
|
||
[20](#20)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6153)
|
||
|
||
Overload resolution is
|
||
performed on a function call created by assembling an argument list[.](#20.sentence-1)
|
||
|
||
The first argument is
|
||
the amount of space requested,
|
||
and has type std::size_t[.](#20.sentence-2)
|
||
|
||
If the type of the allocated object has new-extended alignment,
|
||
the next argument is
|
||
the type's alignment,
|
||
and has type std::align_val_t[.](#20.sentence-3)
|
||
|
||
If the [*new-placement*](#nt:new-placement "7.6.2.8 New [expr.new]") syntax is used,
|
||
the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s* in its [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") are the succeeding arguments[.](#20.sentence-4)
|
||
|
||
If no matching function is found then
|
||
|
||
- [(20.1)](#20.1)
|
||
|
||
if the allocated object type has new-extended alignment,
|
||
the alignment argument is removed from the argument list;
|
||
|
||
- [(20.2)](#20.2)
|
||
|
||
otherwise, an argument that
|
||
is the type's alignment and has type std::align_val_t is added into the argument list immediately after the first argument;
|
||
|
||
and then overload resolution is performed again[.](#20.sentence-5)
|
||
|
||
[21](#21)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6181)
|
||
|
||
[*Example [6](#example-6)*:
|
||
|
||
- [(21.1)](#21.1)
|
||
|
||
new T results in one of the following calls:operator new(sizeof(T))operator new(sizeof(T), std::align_val_t(alignof(T)))
|
||
|
||
- [(21.2)](#21.2)
|
||
|
||
new(2,f) T results in one of the following calls:operator new(sizeof(T), 2, f)operator new(sizeof(T), std::align_val_t(alignof(T)), 2, f)
|
||
|
||
- [(21.3)](#21.3)
|
||
|
||
new T[5] results in one of the following calls:operator new[](sizeof(T) * 5 + x)operator new[](sizeof(T) * 5 + x, std::align_val_t(alignof(T)))
|
||
|
||
- [(21.4)](#21.4)
|
||
|
||
new(2,f) T[5] results in one of the following calls:operator new[](sizeof(T) * 5 + x, 2, f)operator new[](sizeof(T) * 5 + x, std::align_val_t(alignof(T)), 2, f)
|
||
|
||
Here, each instance of x is a non-negative unspecified value
|
||
representing array allocation overhead; the result of the[*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") will be offset by this amount from the value
|
||
returned by operator new[].
|
||
|
||
This overhead may be applied in all
|
||
array [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]")*s*, including those referencing
|
||
a placement allocation function, except when referencing
|
||
the library function operator new[](std::size_t, void*)[.](#21.sentence-1)
|
||
|
||
The amount of overhead may vary from one
|
||
invocation of new to another[.](#21.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
[22](#22)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6216)
|
||
|
||
[*Note [10](#note-10)*:
|
||
|
||
Unless an allocation function has a non-throwing[exception specification](except.spec "14.5 Exception specifications [except.spec]"),
|
||
it indicates failure to allocate storage by throwing astd::bad_alloc exception ([[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2 Allocation functions"), [[except]](except "14 Exception handling"), [[bad.alloc]](bad.alloc "17.6.4.1 Class bad_alloc"));
|
||
it returns a non-null pointer otherwise[.](#22.sentence-1)
|
||
|
||
If the allocation function
|
||
has a non-throwing exception specification,
|
||
it returns null to indicate failure to allocate storage
|
||
and a non-null pointer otherwise[.](#22.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
If the allocation function is a non-allocating
|
||
form ([[new.delete.placement]](new.delete.placement "17.6.3.4 Non-allocating forms")) that returns null,
|
||
the behavior is undefined[.](#22.sentence-3)
|
||
|
||
Otherwise,
|
||
if the allocation function returns null, initialization shall not be
|
||
done, the deallocation function shall not be called, and the value of
|
||
the [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") shall be null[.](#22.sentence-4)
|
||
|
||
[23](#23)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6238)
|
||
|
||
[*Note [11](#note-11)*:
|
||
|
||
When the allocation function returns a value other than null, it must be
|
||
a pointer to a block of storage in which space for the object has been
|
||
reserved[.](#23.sentence-1)
|
||
|
||
The block of storage is assumed to be
|
||
appropriately aligned ([[basic.align]](basic.align "6.8.3 Alignment"))
|
||
and of the requested size[.](#23.sentence-2)
|
||
|
||
The address of the created object will not
|
||
necessarily be the same as that of the block if the object is an array[.](#23.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[24](#24)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6248)
|
||
|
||
A [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") that creates an object of type T initializes that object as follows:
|
||
|
||
- [(24.1)](#24.1)
|
||
|
||
If the [*new-initializer*](#nt:new-initializer "7.6.2.8 New [expr.new]") is omitted, the object is
|
||
default-initialized ([[dcl.init]](dcl.init "9.5 Initializers"))[.](#24.1.sentence-1)
|
||
[*Note [12](#note-12)*:
|
||
If no initialization
|
||
is performed, the object has an indeterminate value[.](#24.1.sentence-2)
|
||
â *end note*]
|
||
|
||
- [(24.2)](#24.2)
|
||
|
||
Otherwise, the [*new-initializer*](#nt:new-initializer "7.6.2.8 New [expr.new]") is interpreted according to
|
||
the initialization rules of [[dcl.init]](dcl.init "9.5 Initializers") for direct-initialization[.](#24.2.sentence-1)
|
||
|
||
[25](#25)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6267)
|
||
|
||
The invocation of the allocation function is sequenced before
|
||
the evaluations of expressions in the [*new-initializer*](#nt:new-initializer "7.6.2.8 New [expr.new]")[.](#25.sentence-1)
|
||
|
||
Initialization of
|
||
the allocated object is sequenced before thevalue computation of the[*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]")[.](#25.sentence-2)
|
||
|
||
[26](#26)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6277)
|
||
|
||
If the [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") creates an array of objects of class type, the destructor is potentially
|
||
invoked ([[class.dtor]](class.dtor "11.4.7 Destructors"))[.](#26.sentence-1)
|
||
|
||
[27](#27)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6282)
|
||
|
||
If any part of the object initialization described above[60](#footnote-60 "This can include evaluating a new-initializer and/or calling a constructor.") terminates by throwing an exception and a suitable deallocation function
|
||
can be found, the deallocation function is called to free the memory in
|
||
which the object was being constructed, after which the exception
|
||
continues to propagate in the context of the [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]")[.](#27.sentence-1)
|
||
|
||
If no unambiguous matching deallocation function can be found,
|
||
propagating the exception does not cause the object's memory to be
|
||
freed[.](#27.sentence-2)
|
||
|
||
[*Note [13](#note-13)*:
|
||
|
||
This is appropriate when the called allocation function does not
|
||
allocate memory; otherwise, it is likely to result in a memory leak[.](#27.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[28](#28)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6302)
|
||
|
||
If the [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") does not begin with
|
||
a unary :: operator and
|
||
the allocated type is a class type T or an array thereof,
|
||
a search is performed for the deallocation function's name
|
||
in the scope of T[.](#28.sentence-1)
|
||
|
||
Otherwise, or if nothing is found,
|
||
the deallocation function's name is looked up by
|
||
searching for it in the global scope[.](#28.sentence-2)
|
||
|
||
[29](#29)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6312)
|
||
|
||
A declaration of a placement deallocation function matches the
|
||
declaration of a placement allocation function if it has the same number
|
||
of parameters and, after parameter transformations ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")), all
|
||
parameter types except the first are identical[.](#29.sentence-1)
|
||
|
||
If
|
||
the lookup finds a single matching deallocation function, that function
|
||
will be called; otherwise, no deallocation function will be called[.](#29.sentence-2)
|
||
|
||
If
|
||
the lookup finds a usual deallocation
|
||
function
|
||
and that function,
|
||
considered as a placement deallocation function, would have been
|
||
selected as a match for the allocation function, the program is
|
||
ill-formed[.](#29.sentence-3)
|
||
|
||
For a non-placement allocation function, the normal deallocation
|
||
function lookup is used to find the matching deallocation
|
||
function ([[expr.delete]](expr.delete "7.6.2.9 Delete"))[.](#29.sentence-4)
|
||
|
||
In any case,
|
||
the matching deallocation function (if any) shall be non-deleted and
|
||
accessible from the point where the [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") appears[.](#29.sentence-5)
|
||
|
||
[*Example [7](#example-7)*: 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; // error: non-placement deallocation function matches// placement allocation function â *end example*]
|
||
|
||
[30](#30)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6345)
|
||
|
||
If a [*new-expression*](#nt:new-expression "7.6.2.8 New [expr.new]") calls a deallocation function, it passes
|
||
the value returned from the allocation function call as the first
|
||
argument of type void*[.](#30.sentence-1)
|
||
|
||
If a placement deallocation function is
|
||
called, it is passed the same additional arguments as were passed to the
|
||
placement allocation function, that is, the same arguments as those
|
||
specified with the [*new-placement*](#nt:new-placement "7.6.2.8 New [expr.new]") syntax[.](#30.sentence-2)
|
||
|
||
If the implementation is allowed
|
||
to introduce a temporary object or make a copy of any argument
|
||
as part of the call to the allocation function,
|
||
it is unspecified whether the same object is used in the call
|
||
to both the allocation and deallocation functions[.](#30.sentence-3)
|
||
|
||
[59)](#footnote-59)[59)](#footnoteref-59)
|
||
|
||
If the conversion function
|
||
returns a signed integer type, the second standard conversion converts to the
|
||
unsigned type std::size_t and thus thwarts any attempt to detect a
|
||
negative value afterwards[.](#footnote-59.sentence-1)
|
||
|
||
[60)](#footnote-60)[60)](#footnoteref-60)
|
||
|
||
This can
|
||
include evaluating a [*new-initializer*](#nt:new-initializer "7.6.2.8 New [expr.new]") and/or calling
|
||
a constructor[.](#footnote-60.sentence-1)
|