For the following program:
int main()
{
new char[4] {"text"}; // #1
new char[5] {"text"}; // #2
new char[] {"text"
Clang is correct in that #1 is ill-formed and #2 is okay.
As Ted Lyngmo noted in a comment, #3 was invalid by the C++ grammar rules, until paper P1009R2 made a change to allow it. A new-expression simply did not allow the possiblity of empty []
in the type, left over from when there was no syntax to initialize the array created by a new-expression, and therefore no way for a compiler to determine the actual size. The paper's changes are accepted in C++20 (but compiler writers will sometimes choose to support "fixes" retroactively in previous -std=
modes).
For the difference between #1 and #2, the initialization of the array object is specified in [expr.new] to follow the direct-initialization rules of [dcl.init]. The general rules for initialization in [dcl.init] early on say if the initializer is a braced-init_list, it is list-initialization. The rules for this in [dcl.init.list] go like:
List-initialization of an object or reference of type
T
is defined as follows:
[C++20 only:] If the braced-init-list contains a designated-initializer-list, ...
If
T
is an aggregate class and...Otherwise, if
T
is a character array and the initializer list has a single element that is an appropriately-typed string-literal ([dcl.init.string]), initialization is performed as described in that subclause....
And so [dcl.init.string] (C++17, latest) gives the actual initialization rules which apply to this code:
An array of {C++17: narrow character type}{C++20: ordinary character type ([basic.fundamental])},
char8_t
array,char16_t
array,char32_t
array, orwchar_t
array can be initialized by {C++17: a narrow}{C++20: an ordinary} string literal, UTF-8 string literal, UTF-16 string literal, UTF-32 string literal, or wide string literal, respectively, or by an appropriately-typed string-literal enclosed in braces ([lex.string]). Successive characters of the value of the string-literal initialize the elements of the array.There shall not be more initializers than there are array elements. [ Example:
char cv[4] = "asdf"; // error
is ill-formed since there is no space for the implied trailing
'\0'
. — end example ]If there are fewer initializers than there are array elements, each element not explicitly initialized shall be zero-initialized ([dcl.init]).
Just like the plain variable definition, when the character array type of a new-expression has a specified bound, it must be large enough for all the characters of a string literal initializing it, including the trailing null character.
(This is an old difference between C and C++: C does allow char cv[4] = "asdf";
and ignores the null character.)