new 연산자(C++)

지정하거나 자리 표시자 형식의 개체 또는 개체 배열을 할당하고 초기화하려고 시도하고 개체(또는 배열의 초기 개체)에 적합한 형식의 0이 아닌 포인터를 반환합니다.

구문

new-expression:
::optnewnew-placementoptnew-type-idnew-initializeropt
::optnewnew-placementopt(type-id)new-initializeropt

new-placement:
( expression-list )

new-type-id:
type-specifier-seqnew-declaratoropt

new-declarator:
ptr-operatornew-declaratoropt
noptr-new-declarator

noptr-new-declarator:
[expression]attribute-specifier-seqopt
noptr-new-declarator[constant-expression]attribute-specifier-seqopt

new-initializer:
(expression-listopt)
braced-init-list

설명

실패 new 하면 0을 반환하거나 예외를 throw합니다. 자세한 내용은 The new and delete Operators를 참조하세요. 사용자 지정 예외 처리 루틴을 작성하고 함수 이름을 인수로 사용하여 런타임 라이브러리 함수를 호출 _set_new_handler 하여 이 기본 동작을 변경할 수 있습니다.

C++/CLI 및 C++/CX에서 관리되는 힙에 개체를 만드는 방법에 대한 자세한 내용은 gcnew를 참조하세요.

참고 항목

Microsoft C++ 구성 요소 확장(C++/CX)은 vtable 슬롯 항목을 추가하는 키워드(keyword) 지원 new 합니다. 자세한 내용은 (vtable의 새 슬롯)을 참조 new 하세요.

C++ 클래스 개체에 대한 메모리를 할당하는 데 사용되는 경우 new 메모리가 할당된 후 개체의 생성자가 호출됩니다.

연산자를 delete 사용하여 연산자가 할당한 메모리의 할당을 취소합니다 new . 연산자를 delete[] 사용하여 연산자가 할당한 배열을 삭제합니다 new .

다음 예제에서는 크기가 dim의 10배인 2차원 문자 배열을 할당한 다음 해제합니다. 다차원 배열을 할당할 때 첫 번째를 제외한 모든 차원은 양수 값으로 계산되는 상수 식이어야 합니다. 가장 왼쪽 배열 차원은 양수 값으로 계산되는 식일 수 있습니다. 연산자를 사용하여 new 배열을 할당하는 경우 첫 번째 차원은 0일 수 있으며 연산자는 new 고유한 포인터를 반환합니다.

char (*pchar)[10] = new char[dim][10];
delete [] pchar;

, type-id 클래스 선언 또는 열거형 선언을 포함constvolatile할 수 없습니다. 다음 식의 형식이 잘못되었습니다.

volatile char *vch = new volatile char[20];

연산자는 new 개체가 아니므로 참조 형식을 할당하지 않습니다.

연산자는 new 함수를 할당하는 데 사용할 수 없지만 함수에 포인터를 할당하는 데 사용할 수 있습니다. 다음 예제에서는 정수를 반환하는 함수에 대한 7개의 포인터 배열을 할당한 다음 해제합니다.

int (**p) () = new (int (*[7]) ());
delete p;

추가 인수 없이 연산 new 자를 사용하고 , /EHa또는 /EHs 옵션으로 /GX컴파일하는 경우 생성자가 예외를 throw하는 경우 컴파일러는 연산 delete 자를 호출하는 코드를 생성합니다.

다음 목록에서는 다음의 new문법 요소를 설명합니다.

new-placement
오버로드 new하는 경우 추가 인수를 전달하는 방법을 제공합니다.

type-id
할당할 형식을 지정합니다. 기본 제공 또는 사용자 정의 형식일 수 있습니다. 형식 사양이 복잡한 경우 괄호로 묶어 바인딩 순서를 강제로 지정할 수 있습니다. 형식은 컴파일러에 의해 형식이 결정되는 자리 표시자(auto)일 수 있습니다.

new-initializer
초기화된 개체의 값을 제공합니다. 배열에 대해 이니셜라이저를 지정할 수 없습니다. 연산자는 new 클래스에 기본 생성자가 있는 경우에만 개체 배열을 만듭니다.

noptr-new-declarator
배열의 범위를 지정합니다. 다차원 배열을 할당할 때 첫 번째를 제외한 모든 차원은 변환 가능한 std::size_t양수 값으로 계산되는 상수 식이어야 합니다. 가장 왼쪽 배열 차원은 양수 값으로 계산되는 식일 수 있습니다. 연결된 attribute-specifier-seq 배열 형식에 적용됩니다.

예: 문자 배열 할당 및 해제

다음 코드 예제는 문자 배열 및 CName 클래스 개체를 할당한 다음 해제합니다.

// expre_new_Operator.cpp
// compile with: /EHsc
#include <string.h>

class CName {
public:
   enum {
      sizeOfBuffer = 256
   };

   char m_szFirst[sizeOfBuffer];
   char m_szLast[sizeOfBuffer];

public:
   void SetName(char* pszFirst, char* pszLast) {
     strcpy_s(m_szFirst, sizeOfBuffer, pszFirst);
     strcpy_s(m_szLast, sizeOfBuffer, pszLast);
   }

};

int main() {
   // Allocate memory for the array
   char* pCharArray = new char[CName::sizeOfBuffer];
   strcpy_s(pCharArray, CName::sizeOfBuffer, "Array of characters");

   // Deallocate memory for the array
   delete [] pCharArray;
   pCharArray = NULL;

   // Allocate memory for the object
   CName* pName = new CName;
   pName->SetName("Firstname", "Lastname");

   // Deallocate memory for the object
   delete pName;
   pName = NULL;
}

예: new 연산자

연산자의 배치 형식 new (크기보다 인수가 많은 폼)을 사용하는 경우 생성자가 예외를 throw하는 경우 컴파일러는 연산자의 배치 형식 delete 을 지원하지 않습니다. 예시:

// expre_new_Operator2.cpp
// C2660 expected
class A {
public:
   A(int) { throw "Fail!"; }
};
void F(void) {
   try {
      // heap memory pointed to by pa1 will be deallocated
      // by calling ::operator delete(void*).
      A* pa1 = new A(10);
   } catch (...) {
   }
   try {
      // This will call ::operator new(size_t, char*, int).
      // When A::A(int) does a throw, we should call
      // ::operator delete(void*, char*, int) to deallocate
      // the memory pointed to by pa2.  Since
      // ::operator delete(void*, char*, int) has not been implemented,
      // memory will be leaked when the deallocation can't occur.

      A* pa2 = new(__FILE__, __LINE__) A(20);
   } catch (...) {
   }
}

int main() {
   A a;
}

할당된 개체 초기화 new

선택적 new-initializer 필드는 연산자의 문법에 포함됩니다 new . 이 필드를 사용하면 사용자 정의 생성자를 사용하여 새 개체를 초기화할 수 있습니다. 초기화가 수행되는 방법에 대한 자세한 내용은 이니셜라이저를 참조 하세요. 다음 예제에서는 연산자를 사용하여 초기화 식을 new 사용하는 방법을 보여 줍니다.

// expre_Initializing_Objects_Allocated_with_new.cpp
class Acct
{
public:
    // Define default constructor and a constructor that accepts
    //  an initial balance.
    Acct() { balance = 0.0; }
    Acct( double init_balance ) { balance = init_balance; }
private:
    double balance;
};

int main()
{
    Acct *CheckingAcct = new Acct;
    Acct *SavingsAcct = new Acct ( 34.98 );
    double *HowMuch = new double { 43.0 };
    // ...
}

이 예제에서는 연산자를 사용하여 개체 CheckingAcctnew 할당되지만 기본 초기화는 지정되지 않았습니다. 따라서 클래스 Acct()의 기본 생성자가 호출됩니다. 그런 다음 개체 SavingsAcct 는 명시적으로 34.98로 초기화된다는 점을 제외하고 동일한 방식으로 할당됩니다. 34.98은 형식이므로 해당 형식 double의 인수를 사용하는 생성자가 초기화를 처리하기 위해 호출됩니다. 마지막으로 클래스가 아닌 형식 HowMuch 은 43.0으로 초기화됩니다.

개체가 클래스 형식이고 해당 클래스에 생성자가 있는 경우(이전 예제와 같이) 다음 조건 중 하나가 충족되는 경우에만 연산자가 개체를 초기화 new 할 수 있습니다.

  • 이니셜라이저에 제공된 인수는 생성자의 인수와 일치합니다.

  • 클래스에 기본 생성자(인수 없이 호출할 수 있는 생성자)가 있습니다.

연산자를 사용하여 new 배열을 할당할 때는 요소별 명시적 초기화를 수행할 수 없습니다. 기본 생성자(있는 경우)만 호출됩니다. 자세한 내용은 기본 인수를 참조 하세요.

메모리 할당이 실패하면(operator new 값 0을 반환) 초기화가 수행되지 않습니다. 이 동작은 존재하지 않는 데이터를 초기화하려는 시도로부터 보호합니다.

함수 호출과 마찬가지로 초기화된 식이 계산되는 순서는 정의되지 않습니다. 또한 메모리 할당이 발생하기 전에 이러한 식을 완전히 평가해서는 안 됩니다. 메모리 할당이 실패하고 연산자가 new 0을 반환하면 이니셜라이저의 일부 식이 완전히 계산되지 않을 수 있습니다.

할당된 개체의 수명 new

연산자를 new 사용하여 할당된 개체는 정의된 범위가 종료될 때 제거되지 않습니다. 연산자는 new 할당하는 개체에 대한 포인터를 반환하므로 프로그램에서 해당 개체에 액세스하고 삭제하기 위해 적절한 범위의 포인터를 정의해야 합니다. 예시:

// expre_Lifetime_of_Objects_Allocated_with_new.cpp
// C2541 expected
int main()
{
    // Use new operator to allocate an array of 20 characters.
    char *AnArray = new char[20];

    for( int i = 0; i < 20; ++i )
    {
        // On the first iteration of the loop, allocate
        //  another array of 20 characters.
        if( i == 0 )
        {
            char *AnotherArray = new char[20];
        }
    }

    delete [] AnotherArray; // Error: pointer out of scope.
    delete [] AnArray;      // OK: pointer still in scope.
}

AnotherArray 포인터가 예제 범위를 벗어나면 개체를 더 이상 삭제할 수 없습니다.

new 작동 방법

연산자를 new 포함하는 식은 new-expression 다음 세 가지 작업을 수행합니다.

  • 할당할 개체에 대한 스토리지를 찾고 예약합니다. 이 단계가 완료되면 올바른 양의 스토리지가 할당되지만 아직 개체는 아닙니다.

  • 개체를 초기화합니다. 초기화가 완료되면 할당된 스토리지가 개체가 되는 데 충분한 정보가 있습니다.

  • 파생되거나 type-id파생된 new-type-id 포인터 형식의 개체에 대한 포인터를 반환합니다. 프로그램에서는 이 포인터를 사용하여 새로 할당된 개체에 액세스합니다.

new 연산자는 함수operator new를 호출합니다. 모든 형식의 배열 및 전역 함수::operator new가 아닌 classstruct개체의 union 경우 스토리지를 할당하기 위해 호출됩니다. 클래스 형식 개체는 클래스별로 자체 operator new 정적 멤버 함수를 정의할 수 있습니다.

컴파일러가 형식T의 개체를 할당하는 연산자를 발견 new 하면 호출을 T::operator new( sizeof(T) ) 실행하거나 사용자 정의 operator new 가 정의::operator new( sizeof(T) )되지 않은 경우 호출을 실행합니다. 연산자가 개체에 new 대해 올바른 양의 메모리를 할당할 수 있는 방법입니다.

참고 항목

인수 operator new 는 형식 std::size_t입니다. 이 형식은 direct.h>, malloc.h>, <memory.h, <search.h>>, <stddef.h, <stdio.h>, <<stdlib.h>>, <string.h> 및 <time.h>에 정의<됩니다.

문법의 옵션을 사용하면 (연산자에 대한new문법 참조) 사양 new-placement 을 사용할 수 있습니다. 매개 변수는 new-placement 사용자 정의 구현에만 사용할 수 있습니다. operator new이 매개 변수는 추가 정보를 전달할 operator new수 있습니다. 필드가 있는 new-placement 식은 클래스 T에 T *TObject = T::operator new( sizeof( T ), 0x0040 ); 멤버operator new가 있는 경우로 변환되고, 그렇지 않으면 T *TObject = ::operator new( sizeof( T ), 0x0040 );로 변환 T *TObject = new ( 0x0040 ) T; 됩니다.

필드의 new-placement 원래 의도는 사용자가 지정한 주소에서 하드웨어 종속 개체를 할당할 수 있도록 하는 것이었습니다.

참고 항목

앞의 예제에서는 필드에 하나의 인수만 표시하지만 이러한 방식으로 전달할 operator new 수 있는 new-placement 추가 인수 수에는 제한이 없습니다.

클래스 형식T에 대해 정의된 경우에도 operator new 다음 예제와 같이 전역 연산 new 자를 명시적으로 사용할 수 있습니다.

T *TObject = ::new TObject;

범위 확인 연산자(::)는 전역 new 연산자를 강제로 사용합니다.

참고 항목

단항 연산자가 있는 식
키워드
newdelete 연산자