신규 및 삭제(C++)
new and delete (C++)
C++프로그래밍 언어로new and delete는 동적 메모리 할당, 객체 구성 및 객체 파괴를 수행하는 언어 구성의 한 쌍이다.[1]
개요
"placement new"라는 형식을 제외하고, 새로운 운영자는 프로세스의 힙에 대한 메모리 할당 요청을 나타낸다.충분한 메모리를 사용할 수 있는 경우, 새 메모리는 메모리를 초기화하며, 필요한 경우 객체 생성자를 호출하고, 새로 할당 및 초기화된 메모리로 주소를 반환한다.[2][3]새로운 요청은 가장 간단한 형태로 다음과 같이 보인다.
p = 새로운 T;
여기서 p는 형식 T의 이전에 선언된 포인터(또는 T의 수퍼클래스와 같이 T 포인터가 할당될 수 있는 다른 유형)이다.할당된 메모리 버퍼에 T 인스턴스를 생성하기 위해 T에 대한 기본 생성자를 호출한다.
T 타입의 객체에 대해 자유 저장소에 메모리가 충분하지 않을 경우, 새로운 요청은 std::bad_alloc 타입의 예외를 던져 실패를 나타낸다.이렇게 하면 할당 결과를 명시적으로 확인할 필요가 없어진다.
new의 할당 해제 상대는 delete이다. delete는 먼저 자신의 주장으로 소멸자(있는 경우)를 호출한 다음 new에 의해 할당된 메모리를 다시 free store로 반환한다.모든 신규 통화는 삭제하라는 호출과 일치해야 한다. 그렇지 않으면 메모리 누수가 발생한다.[1]
새로운 구문에는 메모리 할당과 객체 구성을 보다 세밀하게 제어할 수 있는 몇 가지 변형이 있다.함수 호출과 같은 구문은 기본 생성자가 아닌 다른 생성자를 호출하여 인수를 전달하는 데 사용된다.
p = 새로운 T(언쟁점);
새로 할당된 버퍼를 초기화할 때 기본 생성자 대신 단일 인수 T 생성자를 호출한다.
다른 변종이 단일 객체가 아닌 객체 배열을 할당하고 초기화한다.
p = 새로운 T [N];
이것은 T형식의 N개 객체의 연속적인 배열을 지속적으로 보유할 수 있을 만큼 충분히 큰 메모리 버퍼를 프리 스토어에 요청하고, 배열의 각 요소에 대한 기본 생성자를 호출한다.
새[]와 함께 할당된 메모리는 삭제하기보다는 삭제[] 연산자와 함께 할당 해제되어야 한다.부적절한 양식을 사용하면 정의되지 않은 동작이 발생한다.잘못된 양식을 사용하기 위한 진단 메시지를 생성하기 위해 C++ 컴파일러가 필요하지 않다.
C++11 표준은 추가 구문을 지정한다.
p = 새로운 T[N] {이니셜라이저1, ..., 이니셜라이저n};
각 p[i]를 initializeri+1로 초기화한다.
오류 처리
new가 할당 요청을 처리할 충분한 메모리를 찾을 수 없는 경우, 세 가지 뚜렷한 방법으로 오류를 보고할 수 있다.첫째로, ISO C++ 표준은 프로그램이 new_handler라는 사용자 정의 함수를 C++ 런타임에 등록할 수 있도록 허용한다. 만약 그렇다면, 이 함수는 새로운 오류가 발생할 때마다 호출된다.new_handler는 더 많은 메모리를 사용할 수 있도록 시도하거나, 사용할 수 없는 경우 프로그램을 종료할 수 있다.
new_handler가 설치되지 않은 경우 new는 대신 std::bad_alloc 형식 예외를 발생시킨다.따라서 프로그램은 C의 습관처럼 반환된 포인터의 값을 확인할 필요가 없으며, 예외를 두지 않으면 할당이 성공하였다.
세 번째 오류 처리 방법은 새로운 변형 양식(std::nothrow)에 의해 제공되며, 예외를 발생시키지 않도록 명시한다. 대신, null 포인터가 반환되어 할당 오류를 표시한다.
과부하
특정 유형(클래스)이 해당 인스턴스에 대한 사용자 지정 메모리 할당 알고리즘을 사용하도록 새 연산자를 오버로드할 수 있다.예를 들어, 다음은 첫 번째 새로운 Singleton 호출이 인스턴스를 할당하고 이후의 모든 호출이 동일한 인스턴스를 반환하는 Singleton 패턴의 변형이다.
#include <cstdlib> #include <cstddef> 계급 싱글턴 { 공중의: 정태의 공허하게 하다* 운영자 새로운(찌꺼기::size_t 사이즈를 맞추다) { 만일 (!예시) { 예시 = 찌꺼기::만록의(사이즈를 맞추다); } 다시 세다++; 돌아오다 예시; } 정태의 공허하게 하다 운영자 삭제하다(공허하게 하다*) 예외로 { 만일 (--다시 세다 == 0) { 찌꺼기::무료의(예시); 예시 = 무효의; } } 사유의: 정태의 공허하게 하다* 예시 = 무효의; 정태의 찌꺼기::size_t 다시 세다 = 0; };
이 기능은 특정 과부하 메커니즘이 변경되었지만 C++의 역사에서 초기부터 사용할 수 있었다.언어에 추가된 이유는 객체 지향 C++ 프로그램이 많은 작은 물체를 새로운 것으로 할당하는 경향이 있기 때문이며, 이는 내부적으로 C 할당자(malloc 및 free에 대한 § Relation to free)를 사용하였지만, 일반적인 C 프로그램에 의해 수행되는 보다 적은 수의 대규모 할당에 최적화되었다.스트루스트럽은 초기 애플리케이션에서 C 함수 맬록은 "실제 시스템에서 가장 일반적인 성능 병목 현상"이었으며, 프로그램은 이 기능에 최대 50%를 소비한다고 보고했다.[4]
void *operator new(size_t size)
메모리만 할당하는 C++ 언어 구조를 호출한다.void *operator new(size_t size)
. 할당 단계에서 신규에 의해 사용된다.특정 메모리 할당자를 정의하기 위해 클래스별로 또는 전역적으로 재정의할 수 있다.
malloc 및 free와의 관계
표준 C++가 C 표준 라이브러리를 소급하기 때문에 C 동적 메모리 할당 루틴 malloc, calloc, realloc 및 free도 C++ 프로그래머가 이용할 수 있다.이러한 루틴은 객체 초기화 및 파괴를 수행하지 않기 때문에 대부분의 경우 사용을 금지한다.[5]new와 delete는 사실 수동 객체 초기화의 필요성을 피하기 위해 C++(당시 "C with Classes"라고 불림)의 첫 번째 버전에 도입되었다.[4]
realloc로 할당된 어레이를 증가시키거나 축소할 수 있는 C 루틴과는 달리 new[]로 할당된 메모리 버퍼의 크기를 변경할 수 없다.대신 C++ 표준 라이브러리는 std::vector 템플릿 클래스에서 확장하거나 축소할 수 있는 동적 배열(컬렉션)을 제공한다.
C++ 표준은 new/delete와 c 메모리 할당 루틴의 관계를 명시하지 않지만 new와 delete는 malloc과 free를 중심으로 포장지로 구현된다.[6]예를 들어 새로 할당된 메모리를 자유롭게 할당하거나 Malloc'd 메모리를 삭제하는 등의 두 운영 제품군을 혼합하면 정의되지 않은 동작이 발생하며 실제로 잠금 장치를 해제하지 못해 교착 상태가 되는 등 다양한 재앙적 결과를 초래할 수 있다.[7]
참고 항목
참조
- ^ a b Savitch, Walter (2013). Absolute C++. Pearson. pp. 420–445. ISBN 978-0132846813.
- ^ "IBM Documentation describing C++'s operator new". Archived from the original on 2013-01-03. Retrieved 2013-11-06.
- ^ "Microsoft Visual Studio operator new documentation". Retrieved 2013-11-06.
- ^ a b Stroustrup, Bjarne (1993). A History of C++: 1979–1991 (PDF). Proc. ACM History of Programming Languages Conf.
- ^ Meyers, Scott (1998). Effective C++. Addison-Wesley. p. 21. ISBN 9780201924886.
- ^ Alexandrescu, Andrei (2001). Modern C++ Design: Generic Programming and Design Patterns Applied. Addison-Wesley. p. 68.
- ^ Seacord, Robert C. (2013). Secure Coding in C and C++. Addison-Wesley. 섹션 4.4, 공통 C++ 메모리 관리 오류