Namespaces
Variants
Views
Actions

Talk:cpp/language/new

From cppreference.com
< Talk:cpp‎ | language
Revision as of 01:37, 4 January 2024 by Yaossg (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Contents

[edit] Duplication and constants

Two issues:

  • The table on this page is confusing: rows 1 and 2 are identical, as are 3 and 4. Is there anything on this page that makes some distinction between e.g. 1 and 2?
  • Saying that you can only allocate arrays of compile-time constant integer length probably isn't right; maybe what was meant was that for expressions like new int[n][42], all but the first index must be constant?
--Nate 13:22, 22 June 2012 (PDT)
1) There were parentheses missing in (2) and (4) versions.
2) Yes. I've removed that statement for now.
-- P12 05:34, 23 June 2012 (PDT)

89.228.158.105 08:29, 27 October 2012 (PDT) "If array_n is present, an array of array_n objects is initialized, passing init_params as parameters to the constructor of each object or invoking default constructor if init_params are not present."

like int* int_array = new int[12](1); ? this is not allowed.

Indeed. The standard is quite unclear though - it doesn't say that initialization of an array in such a way is forbidden. The syntax definition apparently allows it. P12 11:47, 27 October 2012 (PDT)
Is there any compiler supporting it?
89.228.158.105 13:23, 4 November 2012 (PST)
int* int_array = new int[12](1); is ill-formed, no compiler should support it. The allowed syntax for array initialization in a new-expression would be the old int* int_array = new int[12](); and the new int* int_array = new int[12]{1};, int* int_array = new int[12]{1,2,3};, etc, supported by clang and gcc for example. See §5.3.4[expr.new]/15 which sends off to §8.5[dcl.init]/16, which says, for this particular case, "if the destination type is an array, the program is ill-formed" --Cubbi 22:14, 4 November 2012 (PST)

[edit] Undefined behavior in example.

The example of the placement new section invokes undefined behavior.

char* ptr = new char[sizeof(T)]; // allocate memory
T* tptr = new(ptr) T;            // construct in allocated storage ("place")
tptr->~T();                      // destruct
delete[] ptr;                    // deallocate memory

After the char* provides storage, it's lifetime as an object ends, as its memory is reused. The new object has a different type which is why it's not legal to still use that pointer for deletion.

See this from [expr.delete] of draft N4141 (practically identical with C++14) or any newer (or most likely also earilier draft).

"In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined."

Maybe it would be better to replace the example with one in which stack-memory is used and no delete is called. 134.101.18.208 05:09, 6 September 2020 (PDT)

I don't think the former code results in undefined behavior.
  • First, the new object of type T has been destroyed, so there is no object of difference type.
  • Second, according to C++14 [basic.life]/5.1, even if lifetime of the char array is considered ended (see below), ptr can be still used in the delete expression.
  • Third, according to C++17 [basic.life]/1.4, the new object is nested within the char array, and thus the array is still living even after the placement new.
  • The change on "providing storage" is introduced via P0137R1, which can be considered a defect report against C++98 (except for parts for std::launder). Currently cppreference treats "providing storage" as a new feature in C++17, which is arguable.
  • Currently the rule of providing storage is inconsistent for char array. See N4861 [intro.object]. I've mailed CWG for this.
--Fruderica (talk) 05:50, 6 September 2020 (PDT)
re: your second point: the C++14 standard describes the period of time to which it refers to here as "before being reused". But it was reused, even if by an object whose lifetime has likewise ended. Might that change anything? 2003:F6:273B:DB87:88C6:710A:CDFE:6C94 11:42, 6 September 2020 (PDT)


You have convinced me that the "provides storage" wording would make this well-defined for unsigned char or std::byte, let's see if you can get a response from CWG regarding plain char.
Additionally, i think that the static type dynamic type mismatch does not occur because ptr never actually changes dynamic type. 134.101.18.208 15:27, 6 September 2020 (PDT)
I believe that even if the array doesn't provide storage for the T object and it's lifetime ends after placement new, the behavior is still well-defined in some cases:
struct T { /*...*/ };
static_assert(alignof(T) <= alignof(int), "");
 
auto pi = new int[(sizeof(T) - 1) / sizeof(int) + 1];
auto pt = new (ptr) T{}; // lifetime of the array ends: it's reused
pt->~T(); // lifetime of the T object ends,
// now there is no living object in the allocated storage
// and thus there's no object of type other than int in the storage
delete[] pi;
// well-defined: int is trivially destructible
I get your meaning... I still consider that "Before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released" simply means "the storage has been allocated but there are no living objects on it", I'll ask CWG for it.
--Fruderica (talk) 02:03, 8 September 2020 (PDT)

[edit] Unknown length expression

Regarding this example:

   double* p = new double[]{1,2,3}; // creates an array of type double[3]

I've been searching for a while for a justification for this. As far as I can tell, neither GCC 8 nor MSVC 14 allow a new-expression without an array length expression. After searching the current draft standard and the 2003, 2011, and 2017 drafts, I can't find any language that allows this syntax. Since 2011, the grammar specification for noptr-new-declarator (7.6.2.8) is explicit in requiring an expression, and the 2003 standard (at 5.3.4) explicitly specifies a call to the global operator new[]() function specified in 3.7.3.1, which in turn does not allow a defaulted arguments.

Does anyone know of a citation for this syntax, in the standards or in compiler extensions?

Greyfade (talk) 11:54, 2 August 2021 (PDT)

It's just expr.new/8 orginally from C++11, for an array type of unknown bound --Cubbi (talk) 12:37, 2 August 2021 (PDT)

[edit] Probable incorrect paragraph

Following paragraph seems incorrect:

If the value in the first dimension is erroneous for any of these reasons,

Should it be like this?

If the value in the first dimension is erroneous for any of these reasons,

Yaossg (talk) 01:37, 4 January 2024 (PST)