Skip to content

Commit eb6cbf0

Browse files
committed
Document Placement NewExpression
1 parent a453ed8 commit eb6cbf0

File tree

2 files changed

+98
-5
lines changed

2 files changed

+98
-5
lines changed

spec/class.dd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1439,7 +1439,7 @@ $(H3 $(LNAME2 anonymous, Anonymous Nested Classes))
14391439

14401440
$(GRAMMAR
14411441
$(GNAME NewAnonClassExpression):
1442-
$(D new) $(D class) $(GLINK ConstructorArgs)$(OPT) $(GLINK AnonBaseClassList)$(OPT) $(GLINK2 struct, AggregateBody)
1442+
$(D new) $(GLINK2 expression, PlacementExpression)$(OPT) $(D class) $(GLINK ConstructorArgs)$(OPT) $(GLINK AnonBaseClassList)$(OPT) $(GLINK2 struct, AggregateBody)
14431443

14441444
$(GNAME ConstructorArgs):
14451445
$(D $(LPAREN)) $(GLINK2 expression, NamedArgumentList)$(OPT) $(D $(RPAREN))

spec/expression.dd

Lines changed: 97 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2920,15 +2920,18 @@ $(H3 $(LNAME2 new_expressions, New Expressions))
29202920

29212921
$(GRAMMAR
29222922
$(GNAME NewExpression):
2923-
$(D new) $(GLINK2 type, Type)
2924-
$(D new) $(GLINK2 type, Type) $(D [) $(GLINK AssignExpression) $(D ])
2925-
$(D new) $(GLINK2 type, Type) $(D $(LPAREN)) $(GLINK NamedArgumentList)$(OPT) $(D $(RPAREN))
2923+
$(D new) $(GLINK PlacementExpression)$(OPT) $(GLINK2 type, Type)
2924+
$(D new) $(GLINK PlacementExpression)$(OPT) $(GLINK2 type, Type) $(D [) $(GLINK AssignExpression) $(D ])
2925+
$(D new) $(GLINK PlacementExpression)$(OPT) $(GLINK2 type, Type) $(D $(LPAREN)) $(GLINK NamedArgumentList)$(OPT) $(D $(RPAREN))
29262926
$(GLINK2 class, NewAnonClassExpression)
2927+
2928+
$(GNAME PlacementExpression):
2929+
$(LPAREN) $(GLINK AssignExpression) $(RPAREN)
29272930
)
29282931

29292932
$(P $(I NewExpression)s allocate memory on the
29302933
$(DDLINK spec/garbage, Garbage Collection, garbage
2931-
collected) heap by default.
2934+
collected) heap unless there is a $(RELATIVE_LINK2 PlacementExpression, PlacementExpression).
29322935
)
29332936

29342937
$(P `new T` constructs an instance of type `T` and default-initializes it.
@@ -3037,6 +3040,96 @@ $(H4 $(LNAME2 new_multidimensional, Multidimensional Arrays))
30373040
}
30383041
-----------
30393042

3043+
$(H4 $(LNAME2 PlacementExpression, Placement Expression))
3044+
3045+
$(P The $(I PlacementExpression) explicitly provides the storage for $(I NewExpression) to initialize with
3046+
the newly created value, rather than using the $(DDLINK spec/garbage, Garbage Collection, garbage
3047+
collected) heap.)
3048+
3049+
$(P If $(I Type) is a basic type or a struct, the $(I PlacementExpression) must produce an lvalue that has a size
3050+
larger or equal to $(D sizeof($(I Type))).)
3051+
3052+
$(P The $(I Type) of the $(I PlacementExpression) need not be the same as the $(I Type) of the object being created.)
3053+
3054+
$(P Alternatively, the $(I PlacementExpression) can be a dynamic array, which must represent sufficient memory
3055+
for the object being created.)
3056+
3057+
$(BEST_PRACTICE Using a static array of `void` is preferred for the $(I PlacementExpression).)
3058+
3059+
$(P The lifetime of the object presented as an lvalue ends with the execution of the $(I NewExpression),
3060+
and a new lifetime of the placed object starts after the execution.)
3061+
3062+
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
3063+
---
3064+
struct S
3065+
{
3066+
float d;
3067+
int i;
3068+
char c;
3069+
}
3070+
3071+
void main()
3072+
{
3073+
S s;
3074+
S* p = new (s) S(); // lifetime of s ends, lifetime of *p begins
3075+
assert(p.i == 0 && p.c == 0xFF);
3076+
}
3077+
---
3078+
)
3079+
3080+
(If Type is a class, the $(I PlacementExpression) must produce an lvalue of type that is of a
3081+
sufficient size to hold the class object such as `void[__traits(classInstanceSize, Type)]`
3082+
or a dynamic array representing sufficient memory for the class object.)
3083+
3084+
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
3085+
---
3086+
class C
3087+
{
3088+
int i, j = 4;
3089+
}
3090+
3091+
void main()
3092+
{
3093+
void[__traits(classInstanceSize, C)] k;
3094+
C c = new(k) C;
3095+
assert(c.j == 4);
3096+
assert(cast(void*)c == cast(void*)k.ptr);
3097+
}
3098+
---
3099+
)
3100+
3101+
$(P $(I PlacementExpression) cannot be used for associative arrays, as associative arrays
3102+
are designed to be on the GC heap. The size of the associative array allocated is determined
3103+
by the runtime library, and cannot be set by the user.)
3104+
3105+
$(P The use of $(PlacementExpression) is not allowed in `@safe` code.)
3106+
3107+
$(P To allocate storage with an allocator function such as `malloc()`, a simple template can be used:)
3108+
3109+
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
3110+
---
3111+
import core.stdc.stdlib;
3112+
3113+
struct S { int i = 1, j = 4, k = 9; }
3114+
3115+
ref void[T.sizeof] mallocate(T)()
3116+
{
3117+
return malloc(T.sizeof)[0 .. T.sizeof];
3118+
}
3119+
3120+
void main()
3121+
{
3122+
S* ps = new(mallocate!S()) S;
3123+
assert(ps.i == 1);
3124+
assert(ps.j == 4);
3125+
assert(ps.k == 9);
3126+
}
3127+
---
3128+
)
3129+
3130+
3131+
3132+
30403133
$(H3 $(LNAME2 typeid_expressions, Typeid Expressions))
30413134

30423135
$(GRAMMAR

0 commit comments

Comments
 (0)