C ++에서 'new'및 'delete'가 더 이상 사용되지 않습니까?


68

다른 크기의 배열 선언과 관련된 퀴즈를 우연히 발견했습니다. 가장 먼저 떠 올린 것은 다음과 같이 new명령에 동적 할당을 사용해야한다는 것입니다 .

while(T--) {
   int N;
   cin >> N;
   int *array = new int[N];
   // Do something with 'array'
   delete[] array;
}

그러나 솔루션 중 하나가 다음과 같은 경우를 허용한다는 것을 알았습니다.

while(T--) {
    int N;
    cin >> N;
    int array[N];
    // Do something with 'array'
}

약간의 연구를 한 후에 g ++이 이것을 허용한다는 것을 읽었지만 계속 생각하면 동적 할당을 사용해야합니까? 아니면 컴파일러가 이것을 동적 할당으로 변환합니까?

삭제 기능이 포함되어 있습니다. 그러나 여기서 질문은 메모리 누수에 관한 것이 아닙니다.


54
두 번째 예는 C ++의 일부가 아닌 가변 길이 배열 을 사용합니다 . 이 경우 std::vector대신 ( std::vector<int> array(N);)을 사용하십시오.
일부 프로그래머 친구

7
귀하의 질문에 대한 직접적인 대답은 다음과 같아야합니다. 아니오, 더 이상 사용되지 않습니다. 최신 버전의 C ++에서는 메모리 소유권 관리 (스마트 포인터)를 단순화하는 많은 기능을 제공하지만 new OBJ직접 호출 하여 객체를 할당하는 것이 일반적 입니다.
pptaszni

8
사람들이 메모리 누수에 대해 얘기하는 이유에 대해 혼동하는 다른 사람들을 위해, 질문은 질문에 중요하지이었다 버그 수정 편집 한
마이크 카론

4
@Mannoj는 동적 및 자동이라는 용어를 사용하여 힙 및 스택을 선호합니다. 드물지만 힙과 스택없이 C ++을 구현할 수 있습니다.
user4581301

1
C ++에서는 더 이상 사용되지 않으며 아무것도하지 않습니다. 이것이 C ++의 의미 중 일부입니다.
JoelFan

답변:


114

당신이 보여주는 스 니펫은 관용적이고 현대적인 C ++ 코드가 아닙니다.

new그리고 delete(및 new[]delete[])는 C ++에서 더 이상 사용되지 않으며 결코 사용되지 않습니다. 여전히 동적으로 할당 된 객체를 인스턴스화 하는 방법입니다. 그러나 항상 a new와 a delete(와 a) new[]를 일치시켜야하므로 delete[]이를 보장하는 (라이브러리) 클래스 내에 유지하는 것이 가장 좋습니다. C ++ 프로그래머가 왜 'new'사용을 최소화해야합니까?를 참조하십시오 . .

첫 번째 스 니펫은 "나이키 (naked)" new[]를 사용한 다음 delete[]생성 된 배열 을 절대 사용하지 않습니다 . 문제입니다. std::vector여기에 필요한 모든 것이 잘됩니다. 그것은 new배후의 어떤 형태를 사용하지만 (구현 세부 사항으로 뛰어 들지 않을 것입니다), 당신이 신경 써야 할 모든 것에 대해 역동적 인 배열이지만 더 좋고 안전합니다.

두 번째 스 니펫은 일부 컴파일러가 C ++에서 확장으로 허용 하는 C 기능인 "VLA (variable length arrays)"를 사용 합니다. 와 달리 newVLA는 기본적으로 스택 (매우 제한된 리소스)에 할당됩니다. 그러나 더 중요한 것은 표준 C ++ 기능이 아니며 이식성이 없기 때문에 피해야한다는 것입니다. 그것들은 동적 (즉, 힙) 할당을 대체하지 않습니다.


3
VLA는 공식적으로 표준에는 없지만 VLA는 모든 주요 컴파일러에서 지원되므로이를 피할 지 여부를 결정하는 것은 이식성에 대한 현실적인 관심사보다 스타일 / 선호의 문제에 더 가깝습니다.
스택 추적기

4
또한 VLA 적 함수의 실행 시간보다 오래하지 않도록 당신이 배열을 반환하거나 다른 곳을 저장할 수 없습니다 기억
루슬란

16
@StackTracer MSVC는 VLA를 지원하지 않습니다. 그리고 MSVC는 가장 중요한 "주요 컴파일러"입니다.
Max Langhof

2
"Qt 클래스 클래스에는 모두 가비지 콜렉터가 있으므로 작업을 수행하는 경우가 아니라 "항상 새 항목을 삭제와 일치 시켜야 new합니다. " GUI 요소의 경우, 상위 위젯이 닫히면 하위가 범위를 벗어나서 자동으로 가비지 수집됩니다.
vsz

6
@vsz Qt에서도 각각은 new여전히 일치합니다 delete. 단지 deletes와 동일한 코드 블록이 아니라 부모 위젯에 의해 수행됩니다 new.
jjramsey

22

글쎄, 우선, new/ delete더 이상 사용되지 않습니다.

특정한 경우에는 이것이 유일한 해결책은 아닙니다. 당신이 선택하는 것은 "배열로 무언가를해라"라는 주석 아래에 무엇이 숨겨져 있는지에 달려 있습니다.

두 번째 예는 비표준 VLA 확장을 사용하여 스택에 배열을 맞추려고합니다. 여기에는 크기 제한 및 어레이가 범위를 벗어난 후이 메모리를 사용할 수 없다는 특정 제한이 있습니다. 당신은 그것을 움직일 수 없으며, 스택이 풀리면 "사라집니다".

따라서 유일한 목표는 로컬 계산을 수행 한 다음 데이터를 버리는 것입니다. 실제로 잘 작동 할 수 있습니다. 그러나보다 강력한 방법은 메모리를 동적으로 할당하는 것입니다 std::vector. 그렇게하면 런타임 값 (우리가 함께 할 것입니다)을 기반으로 필요한만큼 많은 요소를위한 공간을 만들 수 있지만, 자체적으로 깔끔하게 정리되고 이동할 수 있습니다 나중에 메모리를 계속 사용하려면이 범위의

처음으로 다시 돌고, vector 것이다 아마 사용 new깊은 몇 층을, 그러나 제시 인터페이스가 훨씬 우수한 당신은 그와 관련되어서는 안된다. 그런 의미에서 사용 new하고 delete낙심 간주 될 수 있습니다.


1
"... 몇층 더 깊음"에 유의하십시오. 자체 컨테이너를 구현하려는 경우 여전히 newand 사용을 피해야 delete하지만 대신 같은 스마트 포인터를 사용해야 std::unique_pointer합니다.
최대

1
실제로는std::unique_ptr
user253751

2
@Max : std::unique_ptr의 기본 소멸자 호출 delete또는 delete[]소유 객체에 의해 할당 된해야한다는 것을 의미, new또는 new[]호출에 숨겨진 된 어쨌든, std::make_unique14 C ++ 때문이다.
Laurent LA RIZZA

15

두 번째 예제에서는 실제로 C99 ( C ++가 아닌 ) 기능인 가변 길이 배열 (VLA)을 사용 하지만 그럼에도 g ++에서 지원합니다 .

이 답변 도 참조하십시오 .

가변 길이 배열은 new/ delete와 다르며 어떤 식 으로든 "더 이상 사용되지 않습니다".

또한 VLA는 ISO C ++ 이 아닙니다 .


13

최신 C ++은 동적 할당으로보다 쉽게 ​​작업 할 수있는 방법을 제공합니다. 스마트 포인터는 참조 된 데이터 구조가 범위를 벗어나 자마자 예외 (허용 된 경우 어디서나 발생할 수 있음) 및 조기 반환 후 정리를 처리 할 수 ​​있으므로 대신 다음을 사용하는 것이 좋습니다.

  int size=100;

  // This construct requires the matching delete statement.
  auto buffer_old = new int[size];

  // These versions do not require `delete`:
  std::unique_ptr<int[]> buffer_new (new int[size]);
  std::shared_ptr<int[]> buffer_new (new int[size]); 
  std::vector<int> buffer_new (size);  int* raw_access = buffer_new.data();

C ++ 14에서 다음을 작성할 수도 있습니다.

auto buffer_new = std::make_unique<int[]>(size);

이것은 더 멋지게 보이고 할당이 실패하면 메모리 누수를 방지합니다. C ++ 20에서 할 수있는만큼

auto a = std::make_shared<int[]>(size);

이것은 나를 위해 gcc 7.4.0으로 작성할 때 여전히 컴파일되지 않습니다. 이 두 예 auto에서는 왼쪽에 형식 선언 대신 사용 합니다. 모든 경우에 평소와 같이 배열을 사용하십시오.

buffer_old[0] = buffer_new[0] = 17;

C ++은 수년 동안 메모리 누수 new와 충돌 delete로 인해 수년 동안 소멸되어 다른 언어로 전환하기위한 논쟁의 중심이되었습니다. 피하는 것이 좋습니다.


당신은 피해야 unique/shared_ptr찬성 생성자를 make_unique/shared뿐만 아니라 당신이 (사용 두 번 구성 유형을 작성할 필요가 없습니다, auto)하지만 건설 도중에 실패하는 경우 (당신이 실패 할 수있는 유형을 사용하는 경우) 당신은 메모리 또는 자원을 유출 위험하지 않습니다
Simon Buchan

2
make_unique는 C ++ 14의 배열과 C ++ 20의 make_shared에서만 사용할 수 있습니다. 이것은 여전히 ​​기본 설정이 아니기 때문에 std :: make_shared <int []> (size)를 제안하면 다소 앞서 보았습니다.
Audrius Meskauskas

그럴 수 있지! 나는 make_shared<int[]>당신이 거의 항상 원 vector<int>하지만 알아야 할 때 많이 사용하지 않습니다 .
Simon Buchan

과도한 학자 인,하지만 IIRC는 unique_ptr생성자 정도, nothrow입니다 T그래서 거기에 누출의 위험이 없습니다, 생성자 nothrow 가지고 unique_ptr(new int[size])shared_ptr"예외가 발생하는 경우 T가 배열 형식이 아닌 경우, 삭제 페이지를 호출, 삭제 [다음있다 ] p 그렇지 않으면. "와 동일한 효과를 갖습니다 unique/shared_ptr(new MyPossiblyAllocatingType[size]). 위험은입니다 .
Simon Buchan

3

newdelete 는 더 이상 사용되지 않습니다.

new 연산자로 만든 객체는 참조로 전달할 수 있습니다. delete를 사용하여 객체를 삭제할 수 있습니다.

새로운 언어와 삭제는 언어의 기본 측면입니다. new 및 delete를 사용하여 객체의 지속성을 관리 할 수 ​​있습니다. 이것들은 더 이상 사용되지 않을 것입니다.

int array [N] 문 은 배열을 정의하는 방법입니다. 배열은 둘러싸는 코드 블록의 범위 내에서 사용될 수 있습니다. 객체가 다른 함수에 전달되는 방식처럼 전달 될 수 없습니다.


2

첫 번째 예제 delete[]는 끝에 가 필요합니다 . 그렇지 않으면 메모리 누수가 발생합니다.

두 번째 예는 C ++에서 지원하지 않는 가변 배열 길이를 사용합니다. 이것은 단지 어레이 길이 일정한 표현이 가능 .

이 경우 std::vector<>솔루션 으로 사용하는 것이 유용합니다 . 배열에서 수행 할 수있는 모든 작업을 템플릿 클래스로 래핑합니다.


3
"C ++ 11까지"는 무엇을 의미합니까? VLA는 결코 표준의 일부가되지 않았다고 확신합니다.
churill

184 페이지의 c ++ 14 표준 [c ++ 14 standard] ( isocpp.org/files/papers/N3690.pdf ) 8.3.4 장
zig razor

4
그게 전부하지 . 표준 있지만 초안과 내가 말할 수있는까지로 표준 안으로 들어가지는 못했습니다 "바인딩 런타임의 배열"에 대한 부분은 cppreference . 블라스가 언급하지 않습니다
churill

1
@zigrazor cppreference.com에는 각 표준의 게시 전 / 후에 가장 가까운 초안에 대한 링크 목록 이 있습니다. 공표 된 표준은 자유롭게 구할 수 없지만 초안은 매우 근접해야합니다. 문서 번호에서 알 수 있듯이 연결된 초안은 C ++ 14의 이전 버전입니다.
호두

2
@learning_dude 표준에서 지원 되지 않습니다 . 대답은 (지금은) 정확합니다 (짧지 만). GCC 가 비표준 확장 으로 허용하기 때문에 당신에게만 효과가 있습니다 .
호두

-4

구문은 C ++처럼 보이지만 관용구는 일반 Old Algol60과 유사합니다. 다음과 같은 코드 블록을 갖는 것이 일반적이었습니다.

read n;
begin
    integer array x[1:n];
    ... 
end;

예제는 다음과 같이 쓸 수 있습니다.

while(T--) {
    int N;
    cin >> N;
    {
        int array[N];
        // Do something with 'array'
    }
}

나는 때때로 현재 언어에서 이것을 놓쳤다.)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.