Movatterモバイル変換


[0]ホーム

URL:


cppreference.com
Namespaces
Variants
    Actions

      new expression

      From cppreference.com
      <cpp‎ |language
       
       
      C++ language
      General topics
      Flow control
      Conditional execution statements
      Iteration statements (loops)
      Jump statements
      Functions
      Function declaration
      Lambda function expression
      inline specifier
      Dynamic exception specifications(until C++17*)
      noexcept specifier(C++11)
      Exceptions
      Namespaces
      Types
      Specifiers
      constexpr(C++11)
      consteval(C++20)
      constinit(C++20)
      Storage duration specifiers
      Initialization
      Expressions
      Alternative representations
      Literals
      Boolean -Integer -Floating-point
      Character -String -nullptr(C++11)
      User-defined(C++11)
      Utilities
      Attributes(C++11)
      Types
      typedef declaration
      Type alias declaration(C++11)
      Casts
      Memory allocation
      new expression
      Classes
      Class-specific function properties
      Special member functions
      Templates
      Miscellaneous
       
      Expressions
      General
      Literals
      Operators
      Conversions
       

      Creates and initializes objects with dynamicstorage duration, that is, objects whose lifetime is not necessarily limited by the scope in which they were created.

      Contents

      [edit]Syntax

      ::(optional)new(type )new-initializer (optional) (1)
      ::(optional)newtypenew-initializer (optional) (2)
      ::(optional)new(placement-args )(type )new-initializer (optional) (3)
      ::(optional)new(placement-args )typenew-initializer (optional) (4)
      1,2) Attempts to create an object of type, denoted by thetype-idtype, which may be array type, and may include aplaceholder type specifier(since C++11), or include a class template name whose argument is to be deduced byclass template argument deduction(since C++17).
      3,4) Same as(1,2), but provides additional arguments to the allocation function, seeplacementnew.

      [edit]Explanation

      type - the target type-id
      new-initializer - a parentheses-enclosed expression list or abrace-enclosed initializer list(since C++11)
      placement-args - additional placement arguments


      Thenew expression attempts to allocate storage and then attempts to construct and initialize either a single unnamed object, or an unnamed array of objects in the allocated storage. Thenew expression returns a prvalue pointer to the constructed object or, if an array of objects was constructed, a pointer to the initial element of the array.

      Syntax(1) or(3) is required iftype includes parentheses:

      newint(*[10])();// error: parsed as (new int) (*[10]) ()new(int(*[10])());// okay: allocates an array of 10 pointers to functions

      In addition,type is parsed greedily: it will be taken include every token that can be a part of a declarator:

      newint+1;// okay: parsed as (new int) + 1, increments a pointer returned by new intnewint*1;// error: parsed as (new int*) (1)

      Thenew-initializer is not optional if

      (since C++11)
      • a class template is used intype whose arguments need to bededuced.
      (since C++17)
      double* p= newdouble[]{1,2,3};// creates an array of type double[3]auto p= newauto('c');// creates a single object of type char. p is a char* auto q= newstd::integralauto(1);// OK: q is an int*auto q= newstd::floating_pointauto(true)// ERROR: type constraint not satisfied auto r= newstd::pair(1,true);// OK: r is a std::pair<int, bool>*auto r= newstd::vector;// ERROR: element type can't be deduced

      [edit]Dynamic arrays

      Iftype is an array type, all dimensions other than the first must be specified as positiveintegral constant expression(until C++14)converted constant expression of typestd::size_t(since C++14), but (only when using un-parenthesized syntaxes(2) and(4)) the first dimension may bean expression of integral type, enumeration type, or class type with a single non-explicit conversion function to integral or enumeration type(until C++14)any expression convertible tostd::size_t(since C++14). This is the only way to directly create an array with size defined at runtime, such arrays are often referred to asdynamic arrays:

      int n=42;double a[n][5];// errorauto p1= newdouble[n][5];// OKauto p2= newdouble[5][n];// error: only the first dimension may be non-constantauto p3= new(double[n][5]);// error: syntax (1) cannot be used for dynamic arrays

      The behavior is undefined if the value in the first dimension (converted to integral or enumeration type if needed) is negative.

      (until C++11)

      In the following cases the value of the expression specifying the first dimension is invalid:

      • the expression is of non-class type and its value before conversion tostd::size_t is negative;
      • the expression is of class type and its value after user-defined conversion function and before thesecond standard conversion is negative;
      • the value of the expression is larger than some implementation-defined limit;
      • the value is smaller than the number of array elements provided in the brace-enclosed initializer list (including the terminating'\0' on astring literal).

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

      • if, after conversion tostd::size_t, the first dimension is acore constant expression and it ispotentially evaluated, the program is ill-formed,
      • otherwise, if the allocation function that would have been called is non-throwing (includingstd::nothrow overloads not declarednoexcept), thenew expression returns the null pointer of the required result type,
      • otherwise, thenew expression does not call the allocation function, and instead throws an exception of a type that would match ahandler of typestd::bad_array_new_length.
      (since C++11)

      The first dimension of zero is acceptable, and the allocation function is called.

      Ifnew-initializer is a braced-enclosed initializer list, and the first dimension ispotentially evaluated and not acore constant expression, the semantic constraints ofcopy-initializing a hypothetical element of the array from an empty initializer list are checked.

      (since C++11)

      [edit]Allocation

      Thenew expression allocates storage by calling the appropriateallocation function. Iftype is a non-array type, the name of the function isoperator new. Iftype is an array type, the name of the function isoperator new[].

      As described inallocation function, the C++ program may provide global and class-specific replacements for these functions. If thenew expression begins with the optional:: operator, as in::new T or::new T[n], class-specific replacements will be ignored (the function islooked up in globalscope). Otherwise, ifT is a class type, lookup begins in the class scope ofT.

      When calling the allocation function, thenew expression passes the number of bytes requested as the first argument, of typestd::size_t, which is exactlysizeof(T) for non-arrayT.

      Array allocation may supply unspecified overhead, which may vary from one call tonew to the next, unless the allocation function selected is the standard non-allocating form. The pointer returned by thenew expression will be offset by that value from the pointer returned by the allocation function. Many implementations use the array overhead to store the number of objects in the array which is used by thedelete[] expression to call the correct number of destructors. In addition, if thenew expression is used to allocate an array ofchar,unsignedchar, orstd::byte(since C++17), it may request additional memory from the allocation function if necessary to guarantee correct alignment of objects of all types no larger than the requested array size, if one is later placed into the allocated array.

      new expressions are allowed to elide or combine allocations made through replaceable allocation functions. In case of elision, the storage may be provided by the compiler without making the call to an allocation function (this also permits optimizing out unusednew expression). In case of combining, the allocation made by anew expressionE1 may be extended to provide additional storage for anothernew expressionE2 if all of the following is true:

      1) The lifetime of the object allocated byE1 strictly contains the lifetime of the object allocated byE2.
      2)E1 andE2 would invoke the same replaceable global allocation function.
      3) For a throwing allocation function, exceptions inE1 andE2 would be first caught in the same handler.

      Note that this optimization is only permitted whennew expressions are used, not any other methods to call a replaceable allocation function:delete[] newint[10]; can be optimized out, butoperator delete(operator new(10)); cannot.

      (since C++14)

      During an evaluation of aconstant expression, a call to an allocation function is always omitted. Onlynew expressions that would otherwise result in a call to a replaceable global allocation function can be evaluated in constant expressions.

      (since C++20)

      [edit]Placementnew

      Ifplacement-args are provided, they are passed to the allocation function as additional arguments. Such allocation functions are known as "placementnew", after the standard allocation functionvoid*operator new(std::size_t,void*), which simply returns its second argument unchanged. This is used to construct objects in allocated storage:

      // within any block scope...{// Statically allocate the storage with automatic storage duration// which is large enough for any object of type “T”.    alignas(T)unsignedchar buf[sizeof(T)];     T* tptr= new(buf) T;// Construct a “T” object, placing it directly into your// pre-allocated storage at memory address “buf”.     tptr->~T();// You must **manually** call the object's destructor// if its side effects is depended by the program.}// Leaving this block scope automatically deallocates “buf”.

      Note: this functionality is encapsulated by the member functions of theAllocator classes.

      When allocating an object whose alignment requirement exceeds__STDCPP_DEFAULT_NEW_ALIGNMENT__ or an array of such objects, thenew expression passes the alignment requirement (wrapped instd::align_val_t) as the second argument for the allocation function (for placement forms,placement-arg appear after the alignment, as the third, fourth, etc arguments). If overload resolution fails (which happens when a class-specific allocation function is defined with a different signature, since it hides the globals), overload resolution is attempted a second time, without alignment in the argument list. This allows alignment-unaware class-specific allocation functions to take precedence over the global alignment-aware allocation functions.

      (since C++17)
      new T;// calls operator new(sizeof(T))// (C++17) or operator new(sizeof(T), std::align_val_t(alignof(T))))new T[5];// calls operator new[](sizeof(T)*5 + overhead)// (C++17) or operator new(sizeof(T)*5+overhead, std::align_val_t(alignof(T))))new(2,f) T;// calls operator new(sizeof(T), 2, f)// (C++17) or operator new(sizeof(T), std::align_val_t(alignof(T)), 2, f)

      If a non-throwing allocation function (e.g. the one selected bynew(std::nothrow) T) returns a null pointer because of an allocation failure, then thenew expression returns immediately, it does not attempt to initialize an object or to call a deallocation function. If a null pointer is passed as the argument to a non-allocating placementnew expression, which makes the selected standard non-allocating placement allocation function return a null pointer, the behavior is undefined.

      [edit]Initialization

      The object created by anew expression is initialized according to the following rules.

      Iftype is not an array type, the single object is constructed in the acquired memory area:

      • Ifnew-initializer is a braced-enclosed initializer list, the object islist-initialized.
      (since C++11)

      Iftype is an array type, an array of objects is initialized:

      • Even if the first dimension is zero, the semantic constraints of default-initializing a hypothetical element still need to be met.
      • Even if the first dimension is zero, the semantic constraints of value-initializing a hypothetical element still need to be met.
      (since C++11)
      • Ifnew-initializer is a parentheses-enclosed non-empty expression list, the array isaggregate-initialized.
      (since C++20)

      [edit]Initialization failure

      If initialization terminates by throwing an exception (e.g. from the constructor), the program looks up a matching deallocation function, then:

      • If a suitable deallocation function can be found, the deallocation function is called to free the memory in which the object was being constructed. After that, the exception continues to propagate in the context of thenew expression.
      • If no unambiguous matching deallocation function can be found, propagating the exception does not cause the object’s memory to be freed. It is only appropriate if the called allocation function does not allocate memory, otherwise it is likely to result in a memory leak.

      The scope of thelookup of the matching deallocation function is determined as follows:

      • If thenew expression does not begin with::, and the allocated type is either a class typeT or an array of class typeT, a search is performed for the deallocation function’s name in the class scope ofT.
      • Otherwise, or if nothing is found in theT's class scope, the deallocation function’s name is looked up by searching for it in theglobal scope.

      For a non-placement allocation function, the normal deallocation function lookup is used to find the matching deallocation function (seedelete-expression).

      For a placement allocation function, the matching deallocation function must have the same number of parameter, and each parameter type except the first is identical to the corresponding parameter type of the allocation function (afterparameter transformations).

      • If the lookup finds a single matching deallocation function, that function will be called; otherwise, no deallocation function will be called.
      • If the lookup finds a non-placement 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.

      In any case, the matching deallocation function (if any) must be non-deleted and(since C++11) accessible from the point where thenew expression appears.

      struct S{// Placement allocation function:staticvoid*operator new(std::size_t,std::size_t); // Non-placement deallocation function:staticvoidoperator delete(void*,std::size_t);}; S* p= new(0) S;// error: non-placement deallocation function matches//        placement allocation function

      If a deallocation function is called in anew expression (due to initialization failure), the arguments passed to that function are determined as follows:

      • The first argument is the value (of typevoid*) returned from the allocation function call.
      • Other arguments (only for placement deallocation functions) are theplacement-args passed to the placement allocation function.

      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.

      [edit]Memory leaks

      The objects created bynew expressions (objects with dynamic storage duration) persist until the pointer returned by thenew expression is used in a matchingdelete-expression. If the original value of pointer is lost, the object becomes unreachable and cannot be deallocated: amemory leak occurs.

      This may happen if the pointer is assigned to:

      int* p= newint(7);// dynamically allocated int with value 7p= nullptr;// memory leak

      or if the pointer goes out of scope:

      void f(){int* p= newint(7);}// memory leak

      or due to exception:

      void f(){int* p= newint(7);    g();// may throw    delete p;// okay if no exception}// memory leak if g() throws

      To simplify management of dynamically-allocated objects, the result of anew expression is often stored in asmart pointer:std::auto_ptr(until C++17)std::unique_ptr, orstd::shared_ptr(since C++11). These pointers guarantee that the delete expression is executed in the situations shown above.

      [edit]Notes

      Itanium C++ ABI requires that the array allocation overhead is zero if the element type of the created array is trivially destructible. So does MSVC.

      Some implementations (e.g. MSVC before VS 2019 v16.7) require non-zero array allocation overhead on non-allocating placement arraynew if the element type is not trivially destructible, which is no longer conforming sinceCWG issue 2382.

      A non-allocating placement arraynew expression that creates an array ofunsignedchar, orstd::byte(since C++17) can be used toimplicitly create objects on given region of storage: it ends lifetime of objects overlapping with the array, and then implicitly creates objects of implicit-lifetime types in the array.

      std::vector offers similar functionality for one-dimensional dynamic arrays.

      [edit]Keywords

      new

      [edit]Defect reports

      The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

      DRApplied toBehavior as publishedCorrect behavior
      CWG 74C++98value in the first dimension must have integral typeenumeration types permitted
      CWG 299C++98value in the first dimension must
      have integral or enumeration type
      class types with a single
      conversion function to integral
      or enumeration type permitted
      CWG 624C++98the behavior was unspecified when the
      size of the allocated object would exceed
      the implementation-defined limit
      no storage is obtained and an
      exception is thrown in this case
      CWG 1748C++98non-allocating placementnew need
      to check if the argument is null
      undefined behavior for null argument
      CWG 1992C++11new(std::nothrow)int[N]
      could throwstd::bad_array_new_length
      changed to return a null pointer
      CWG 2102C++98it was unclear whether default/value-initialization is
      required to be well-formed when initializing empty arrays
      required
      CWG 2382C++98non-allocating placement arraynew
      could require allocation overhead
      such allocation overhead disallowed
      CWG 2392C++11the program might be ill-formed even if the
      first dimension is not potentially-evaluated
      well-formed in this case
      P1009R2C++11the array bound could not be
      deduced in anew expression
      deduction permitted

      [edit]See also

      Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/language/new&oldid=178509"

      [8]ページ先頭

      ©2009-2025 Movatter.jp