개인 재정 힙이 C ++에서 어떻게 작동하는지 - 더미

힙이 C ++에서 어떻게 작동하는지 - 더미

차례:

비디오: 동영상 강좌 - 'Do it! C언어 입문' - 16장 메모리 할당 (2/2) 2024

비디오: 동영상 강좌 - 'Do it! C언어 입문' - 16장 메모리 할당 (2/2) 2024
Anonim

힙은 C ++ 프로그램이 필요에 따라 액세스 할 수있는 비정형 메모리 블록입니다. 그 이유와 사용 방법에 대해 알아보십시오.

함수에 대한 포인터를 전달할 수있는 것처럼 함수가 포인터를 반환 할 수도 있습니다. double의 주소를 반환하는 함수는 다음과 같이 선언됩니다.

double * fn (void);

그러나 포인터를 반환 할 때는 매우 조심해야합니다. 위험을 이해하려면 가변 범위에 대해 알아야합니다.

C ++의 제한 범위

범위는 변수가 정의되는 범위입니다. 다음 코드 스 니펫을 고려하십시오.

// 다음 함수는 // 모든 함수에 액세스 할 수 있으며 // 프로그램이 실행되는 동안 정의됩니다 (전역 범위). int intGlobal; // 다음 변수 intChild는 // 함수에만 액세스 할 수 있으며 // C ++이 child () 또는 // function (function scope)을 호출하는 function을 실행하는 동안에 만 정의됩니다. void child (void) {int int // 다음 변수 intParent는 함수 // scope void parent (void) {int intParent = 0; 어린이(); int intLater = 0; int (int nArgs, char * pArgs []) {parent ();}이 프로그램 조각은 변수 intGlobal 선언으로 시작합니다. 이 변수는 프로그램이 종료 될 때까지 실행을 시작한 시점부터 존재합니다. IntGlobal에는 "프로그램 범위가 있습니다. "main () 함수가 호출되기 전에도 변수가"범위에 들어갑니다 "라고 말합니다.

main () 함수는 즉시 parent ()를 호출합니다. parent ()에서 프로세서가 처음 보는 것은 intParent 선언입니다. 이 시점에서 intParent는 범위에 들어갑니다. 즉, intParent가 정의되어 나머지 parent () 함수에 사용할 수 있습니다.

parent ()의 두 번째 명령문은 child () 호출입니다. 다시 한번, 함수 child ()는 지역 변수 인 intChild를 선언합니다. 변수 intChild의 범위는 함수 child ()로 제한됩니다. 엄밀히 말하면, child ()는 intParent에 액세스 할 수 없기 때문에 intParent는 child ()의 범위 내에서 정의되지 않습니다. 그러나 변수 intParent는 child ()가 실행되는 동안 계속 존재합니다.

child ()가 종료되면 intChild 변수가 범위를 벗어납니다. intChild는 더 이상 액세스 할 수 없으며 더 이상 존재하지 않습니다. (intChild에 의해 점유 된 메모리는 다른 것들에 사용될 일반 풀로 반환됩니다.)

parent ()가 계속 실행되면서 변수 intLater가 선언에서 범위 안으로 들어갑니다. parent ()가 main ()으로 돌아 오면 intParent와 intLater가 모두 범위를 벗어납니다.

이 예에서는 intGlobal이 전역 적으로 선언되었으므로이 함수는 세 가지 함수 모두에서 사용할 수 있으며 프로그램 수명 기간 동안 사용할 수 있습니다.

C ++의 범위 문제 검사

다음 코드 세그먼트는 오류없이 컴파일되지만 작동하지 않습니다 (단지 싫어하지 마십시오.):

double * child (void) {double dLocalVariable; return & dLocalVariable;} void parent (void) {double * pdLocal; pdLocal = 자식 (); * pdLocal = 1. 0;}

이 함수의 문제점은 dLocalVariable이 child () 함수의 범위 내에서만 정의된다는 것입니다. 따라서 dLocalVariable의 메모리 주소가 child ()에서 반환 될 때까지 더 이상 존재하지 않는 변수를 참조합니다. dLocalVariable이 이전에 점유 한 메모리는 아마도 다른 용도로 사용되고있을 것입니다.

이 오류는 여러 가지 방법으로 상실 될 수 있기 때문에 매우 일반적입니다. 불행히도이 오류로 인해 프로그램이 즉시 중지되지는 않습니다. 사실, 프로그램은 대부분 잘 작동 할 수 있습니다. 즉, 이전에 dLocalVariable이 차지한 메모리가 즉시 재사용되지 않는 한 프로그램은 계속 작동합니다. 이러한 간헐적 인 문제는 해결하기가 가장 어려운 문제입니다.

C ++에서 힙을 사용하여 솔루션 제공

프로그래머가 준비되기 전에 C ++에서 로컬로 정의 된 메모리를 회수했기 때문에 범위 문제가 발생했습니다. 필요한 것은 프로그래머가 제어하는 ​​메모리 블록입니다. 그녀는 기억을 할당하고 원할 때 되돌릴 수 있습니다. 왜냐하면 C ++은 그것이 좋은 생각이라고 생각하기 때문이 아닙니다. 이러한 메모리 블록을 힙이라고합니다.

힙 메모리는 new 키워드와 할당 할 객체 유형을 사용하여 할당됩니다. 새로운 명령은 지정된 유형의 객체를 보유 할만큼 충분히 큰 힙에서 메모리 덩어리를 분리하고 주소를 반환합니다. 예를 들어, 다음은 힙에서 double 변수를 할당합니다.

double * child (void) {double * pdLocalVariable = new double; return pdLocalVariable;}

이 함수는 이제 제대로 작동합니다. 함수 child ()가 반환 될 때 변수 pdLocalVariable이 범위를 벗어나지 만 pdLocalVariable이 참조하는 메모리는 반환하지 않습니다. new에 의해 반환 된 메모리 위치는 명시 적으로 그 목적을 위해 설계된 delete 키워드를 사용하여 힙에 명시 적으로 반환 될 때까지 범위를 벗어나지 않습니다:

void parent (void) {// child ()는 주소를 반환합니다 블록 힙 메모리의 두 배 * pdMyDouble = child (); // 거기에 값을 저장하십시오. * pdMyDouble = 1. 1; // … // 이제 힙에 메모리를 반환합니다. delete pdMyDouble; pdMyDouble = 0; // …}

여기서 child ()가 반환 한 포인터는 double 값을 저장하는 데 사용됩니다. 기능이 메모리 위치로 완료되면 힙으로 리턴됩니다. 함수 parent ()는 힙 메모리가 반환 된 후에 포인터를 0으로 설정합니다. 이것은 필수 사항은 아니지만 아주 좋은 생각입니다.

프로그래머가 실수로 * pdMyDouble에 항목을 저장하려고 시도하면 프로그램이 즉시 오류 메시지와 함께 충돌합니다.

->

new를 사용하여 힙에서도 배열을 할당 할 수 있지만 delete [] 키워드를 사용하여 배열을 반환해야합니다.

int * nArray = new int [10]; nArray [0] = 0; delete [] nArray;

기술적으로 새로운 int [10]은 새로운 [] 연산자를 호출하지만 새로운 연산자와 동일하게 작동합니다.
힙이 C ++에서 어떻게 작동하는지 - 더미

편집자의 선택

Dragon Go! iPhone 및 iPad 용 앱 - 인형

Dragon Go! iPhone 및 iPad 용 앱 - 인형

Dragon Search를 사용하시는 분이라면 Dragon Go를 사용하는 것이 좋습니다! Nuance는 iPhone 3GS, iPhone 5, iPhone 4, iPod touch (3 세대), iPod touch (4 세대) 및 iPad에서 사용할 수 있도록 무료로 다운로드 할 수있는이 앱을 만들었습니다. (iOS 4.0 이상이어야합니다.) Android 기기에서도 사용할 수 있습니다. 드래곤가! ...

드래곤에서 피할 수있는 10 가지 실수 말하기 - 인형

드래곤에서 피할 수있는 10 가지 실수 말하기 - 인형

모두가 실수를 저지르고 어떤 사람들은 정말 크고 재미있게 만든다. 실수. NaturallySpeaking을 사용하여 많은 실수를 저 지르므로 때때로 수시로 일부를 만들 수도 있습니다. 내가 묻는 것은 다음과 같습니다. 내가 미리 짐작했던 10 가지 분명한 실수를하지 마십시오. 원래의 수. 창조적으로 행동하십시오. 거기서 나가서 ...

NaturallySpeaking을위한 10 가지 시간 절약 팁 - 인형

NaturallySpeaking을위한 10 가지 시간 절약 팁 - 인형

때로는 잘하고 그냥 사용하는 것의 차이 새로운 소프트웨어는 더 지혜롭고 경험 많은 스승의 충고 한 부분입니다. 누군가가 당신에게 전에 말했었 으면 좋을 10 가지가 있습니다. 대화 상자의 단축키 사용 대화 상자, 라디오 버튼, 확인란의 다양한 기능 ...

편집자의 선택

Google SketchUp 8에서 새로운 지형 모델을 만드는 법 - Google에서 모델링 할 때 인형

Google SketchUp 8에서 새로운 지형 모델을 만드는 법 - Google에서 모델링 할 때 인형

SketchUp을 사용하면 지형을 만들어야 할 수 있습니다. 건물에 대한 패치를 모델링하든 센트럴 파크를 다시 디자인하든 기존 데이터로 지형을 모델링 할 수 있습니다. 기존 데이터는 일반적으로 등고선 또는 토폴 라인 형태로 도착합니다. 지형지도에서 볼 수있는 삐걱 거리는 선을 알고 있습니다.

SketchUp에서 드레이프로 경로와 도로를 만드는 법 - 스케치 업에서 드레이프 도구

SketchUp에서 드레이프로 경로와 도로를 만드는 법 - 스케치 업에서 드레이프 도구

드레이프 도구가 작동 함 쿠키 커터와 조금 같다. 그것을 사용하여 객체의 가장자리를 직접 그 아래에있는 다른 표면으로 전송합니다. 아마도 당신은 부드럽게 경 사진 지형을 가지고 있으며, 당신은 그것에 사행 경로를 그리기를 원할 것입니다. 경로는 윤곽선을 따라야합니다.

SketchUp 모델을 3D 인쇄 용 부품으로 자르는 방법 - 인형

SketchUp 모델을 3D 인쇄 용 부품으로 자르는 방법 - 인형

SketchUp 모델 자르기 Intersect Faces 도구를 사용하여 그룹을 결합하는 것과 매우 유사합니다. 더 큰 오브젝트와 교차하여 커팅의 새 가장자리가 될 커터로 지오메트리를 사용할 것입니다. 모델이 매우 단순하고 SketchUp을 사용하는 경우 ...

편집자의 선택

Route Prefix를 사용하여 Junos - dummy에서 라우팅 필터를 생성하는 방법

Route Prefix를 사용하여 Junos - dummy에서 라우팅 필터를 생성하는 방법

라우팅 정책은 특정 경로가 라우팅 테이블에 수용되거나 일부 인접 라우터에 보급되는 것을 방지하기위한 것입니다. 경우에 따라 특정 경로 또는 경로 집합을 일치시키는 것이 유용 할 수 있습니다. 이렇게하려면 경로 필터를 사용합니다. 경로 필터는 특정 IP 주소 또는 접두어 범위에서 일치합니다. ...

Junos 라우터에서 COS의 코드 포인트 별명을 사용하는 방법 - 인형

Junos 라우터에서 COS의 코드 포인트 별명을 사용하는 방법 - 인형

전달 수업은 고통 스러울 수 있습니다. 더 좋은 방법은 코드 포인트 별칭을 사용하는 것입니다. CoS (Class of Service) 정책을 결정할 때 비트 패턴을 지정하는 대신 비트 패턴을 나타내는 별칭 이름을 정의 할 수 있습니다. 이러한 별칭을 코드 포인트 별칭이라고합니다. 간단히 말하자면 코드 포인트를 사용하십시오 ...

Junos 라우팅 정보를 요약하는 방법 - 더미

Junos 라우팅 정보를 요약하는 방법 - 더미

때때로 라우팅 정보를 간단하게 요약 할 수 있습니다 라우터. 예를 들어, 네트워크에서 OSPF를 방금 구성 했으므로 라우팅 테이블에 특정 수의 OSPF 경로가 표시 될 것으로 예상됩니다. show route summary 명령을 실행하여 모든 경로를 볼 수 있습니다 ...