수색…
통사론
- : ( opt ) new ( 표현식 목록 ) ( opt ) new-type-id new-initializer ( opt )
- : ( opt ) new ( 표현식 목록 ) ( opt ) ( 유형 ID ) new-initializer ( opt )
- : :( 선택 ) 캐스트 표현식 삭제
- : :( 선택 ) delete [] cast-expression
- std :: unique_ptr < type-id > var_name (새 형식 -id ( opt )); // C ++ 11
- std :: shared_ptr < type-id > var_name (새 유형 -id ( opt )); // C ++ 11
- std :: shared_ptr < type-id > var_name = std :: make_shared < type-id > ( opt ); // C ++ 11
- std :: unique_ptr < type-id > var_name = std :: make_unique < type-id > ( opt ); // C ++ 14
비고
leading ::
는 new 또는 delete 연산자가 전역 범위에서 검색되도록하여 오버로드 된 클래스 별 new 또는 delete 연산자를 재정의합니다.
new
키워드 뒤에 오는 선택적 인수는 대개 새로운 배치 를 호출하는 데 사용되지만, 선택한 풀에서 메모리를 할당하도록 요청하는 태그와 같이 추가 정보를 할당 자에게 전달하는 데에도 사용할 수 있습니다.
할당 된 타입은 대개 명시 적으로 지정됩니다 ( 예 : new Foo
). 그러나 auto
(C ++ 11 이후) 또는 decltype(auto)
(C ++ 14 이후)으로 작성하여 이니셜 라이저에서 추론 할 수도 있습니다.
할당 된 객체의 초기화는 로컬 변수 초기화와 동일한 규칙에 따라 수행됩니다. 특히 이니셜 라이저 iso가 생략되면 개체가 기본값으로 초기화되고 스칼라 유형이나 스칼라 유형 배열을 동적으로 할당 할 때 메모리가 0이 될 것이라는 보장은 없습니다.
새 표현식 이 []
으로 작성되었는지 여부에 관계없이 new- 표현식으로 작성된 배열 객체는 delete[]
사용하여 파기해야합니다. 예 :
using IA = int[4];
int* pIA = new IA;
delete[] pIA; // right
// delete pIA; // wrong
스택
스택은 실행 중에 임시 값이 저장되는 작은 메모리 영역입니다. 스택에 데이터를 할당하는 것은 모든 메모리가이 목적으로 이미 할당 되었기 때문에 힙 할당에 비해 매우 빠릅니다.
int main() {
int a = 0; //Stored on the stack
return a;
}
스택의 이름은 함수 호출의 체인이 각각의 작은 메모리 섹션을 사용하여 서로 겹쳐 지도록 임시 메모리를 쌓아두기 때문에 명명됩니다.
float bar() {
//f will be placed on the stack after anything else
float f = 2;
return f;
}
double foo() {
//d will be placed just after anything within main()
double d = bar();
return d;
}
int main() {
//The stack has no user variables stored in it until foo() is called
return (int)foo();
}
스택에 저장된 데이터는 변수를 할당 한 범위가 여전히 활성 인 동안에 만 유효합니다.
int* pA = nullptr;
void foo() {
int b = *pA;
pA = &b;
}
int main() {
int a = 5;
pA = &a;
foo();
//Undefined behavior, the value pointed to by pA is no longer in scope
a = *pA;
}
무료 저장소 (힙, 동적 할당 ...)
용어 '힙' 은 스택이 제공하는 메모리와는 독립적으로 할당 및 할당 해제 할 수있는 메모리 영역을 의미하는 일반 컴퓨팅 용어입니다.
C++
에서이 표준 은 더 정확한 용어로 간주되는 Free Store 를 가리 킵니다.
Free Store 에서 할당 된 메모리 영역은 할당 된 원래 범위보다 오래 살 수 있습니다. 스택에 저장하기에는 너무 큰 데이터는 Free Store 에서 할당 할 수도 있습니다.
원시 메모리는 new 및 delete 키워드에 의해 할당 및 할당 해제 될 수 있습니다.
float *foo = nullptr;
{
*foo = new float; // Allocates memory for a float
float bar; // Stack allocated
} // End lifetime of bar, while foo still alive
delete foo; // Deletes the memory for the float at pF, invalidating the pointer
foo = nullptr; // Setting the pointer to nullptr after delete is often considered good practice
고정 길이 배열을 new 와 delete 로 할당하는 것도 가능합니다. 구문은 약간 다릅니다. 배열 할당은 비 배열 할당과 호환되지 않으므로 둘을 섞으면 힙 손상이 발생합니다. 배열을 할당하면 나중에 구현 정의 된 방식으로 삭제할 수 있도록 배열의 크기를 추적하는 메모리가 할당됩니다.
// Allocates memory for an array of 256 ints
int *foo = new int[256];
// Deletes an array of 256 ints at foo
delete[] foo;
new를 사용하고 malloc 과 free 대신에 delete를 사용하면 생성자와 소멸자가 실행됩니다 (스택 기반 객체와 비슷 함). 이것이 malloc 과 free 보다 new 와 delete 를 선호하는 이유입니다.
struct ComplexType {
int a = 0;
ComplexType() { std::cout << "Ctor" << std::endl; }
~ComplexType() { std::cout << "Dtor" << std::endl; }
};
// Allocates memory for a ComplexType, and calls its constructor
ComplexType *foo = new ComplexType();
//Calls the destructor for ComplexType() and deletes memory for a Complextype at pC
delete foo;
C ++ 11 이후에는 소유권을 나타 내기 위해 스마트 포인터를 사용하는 것이 좋습니다.
C ++ 14에서는 std::make_unique
를 STL에 추가하여 naked new 및 delete 대신 std::make_unique
또는 std::make_shared
를 사용하도록 권장 사항을 변경했습니다.
새로운 게재 위치
메모리를 할당하기 위해 프리 스토어에 의존하기를 원하지 않고 new
메모리를 사용하여 맞춤 메모리 할당을 사용하려는 상황이 있습니다.
이러한 상황에서 우리는 'New'연산자를 사용하여 미리 할당 된 메모리 위치에서 메모리를 할당하도록 지시 할 수있는 Placement New
사용할 수 있습니다
예를 들어
int a4byteInteger;
char *a4byteChar = new (&a4byteInteger) char[4];
이 예제에서 a4byteChar
가 가리키는 메모리는 정수 변수 a4byteInteger
를 통해 '스택'에 할당 된 4 바이트입니다.
이런 종류의 메모리 할당의 이점은 프로그래머가 할당을 제어한다는 사실입니다. 위의 예제에서는 a4byteInteger
가 스택에 할당되었으므로 'delete a4byteChar'를 명시 적으로 호출 할 필요가 없습니다.
동적 할당 메모리에 대해서도 동일한 동작을 얻을 수 있습니다. 예를 들어
int *a8byteDynamicInteger = new int[2];
char *a8byteChar = new (a8byteDynamicInteger) char[8];
이 경우에,에 의해 메모리 포인터 a8byteChar
할당 한 동적 메모리를 참조한다 a8byteDynamicInteger
. 그러나이 경우에는 delete a8byteDynamicInteger
를 명시 적으로 호출하여 메모리를 해제해야합니다.
C ++ 클래스의 또 다른 예제
struct ComplexType {
int a;
ComplexType() : a(0) {}
~ComplexType() {}
};
int main() {
char* dynArray = new char[256];
//Calls ComplexType's constructor to initialize memory as a ComplexType
new((void*)dynArray) ComplexType();
//Clean up memory once we're done
reinterpret_cast<ComplexType*>(dynArray)->~ComplexType();
delete[] dynArray;
//Stack memory can also be used with placement new
alignas(ComplexType) char localArray[256]; //alignas() available since C++11
new((void*)localArray) ComplexType();
//Only need to call the destructor for stack memory
reinterpret_cast<ComplexType*>(localArray)->~ComplexType();
return 0;
}