Init
This commit is contained in:
667
cppdraft/expr/new.md
Normal file
667
cppdraft/expr/new.md
Normal file
@@ -0,0 +1,667 @@
|
||||
[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)
|
||||
Reference in New Issue
Block a user