자동 할당과 동적 할당이라는 두 가지 널리 사용되는 메모리 할당 기술이 있습니다. 일반적으로 스택과 힙 각각에 해당하는 메모리 영역이 있습니다.
스택
스택은 항상 순차적으로 메모리를 할당합니다. 메모리를 역순으로 해제해야하기 때문에 그렇게 할 수 있습니다 (선입 선출, 최종 출발 : FILO). 이것은 많은 프로그래밍 언어에서 지역 변수에 대한 메모리 할당 기술입니다. 최소한의 부기를 유지해야하며 할당 할 다음 주소가 암시 적이므로 매우 빠릅니다.
C ++에서는 스토리지가 범위 끝에서 자동으로 청구되므로 이를 자동 스토리지 라고합니다. 현재 코드 블록 (을 사용하여 구분 {}
)의 실행이 완료되면 해당 블록의 모든 변수에 대한 메모리가 자동으로 수집됩니다. 이것은 또한 자원을 정리하기 위해 소멸자 가 호출 되는 순간 입니다.
더미
힙은보다 유연한 메모리 할당 모드를 허용합니다. 부기는 더 복잡하고 할당이 느립니다. 암시 적 릴리스 지점이 없으므로 delete
또는 delete[]
( free
C에서)를 사용하여 메모리를 수동으로 해제해야합니다 . 그러나 암시 적 릴리스 지점이없는 것이 힙 유연성의 핵심입니다.
동적 할당을 사용해야하는 이유
힙 사용이 느리고 잠재적으로 메모리 누수 나 메모리 조각화가 발생하더라도 동적 할당에 대한 사용 사례는 제한이 적으므로 완벽하게 사용됩니다.
동적 할당을 사용해야하는 두 가지 주요 이유 :
컴파일 타임에 필요한 메모리 양을 모릅니다. 예를 들어, 텍스트 파일을 문자열로 읽을 때 일반적으로 파일의 크기를 모르므로 프로그램을 실행할 때까지 할당 할 메모리 양을 결정할 수 없습니다.
현재 블록을 떠난 후에 지속되는 메모리를 할당하려고합니다. 예를 들어 string readfile(string path)
파일의 내용을 반환 하는 함수를 작성하려고 할 수 있습니다. 이 경우 스택이 전체 파일 내용을 보유 할 수 있어도 함수에서 복귀하여 할당 된 메모리 블록을 유지할 수 없습니다.
동적 할당이 종종 불필요한 이유
C ++에는 소멸 자라는 깔끔한 구조가 있습니다. 이 메커니즘을 사용하면 리소스 수명을 변수 수명과 정렬하여 리소스를 관리 할 수 있습니다. 이 기술을 RAII 라고 하며 C ++의 특징입니다. 리소스를 개체로 "랩핑"합니다. std::string
완벽한 예입니다. 이 스 니펫 :
int main ( int argc, char* argv[] )
{
std::string program(argv[0]);
}
실제로 다양한 양의 메모리를 할당합니다. std::string
소멸자에서 힙 해제를 사용하여 객체의 메모리를 할당합니다. 이 경우 리소스를 수동으로 관리 하지 않아도 동적 메모리 할당의 이점을 얻을 수 있습니다.
특히,이 스 니펫에서 다음을 의미합니다.
int main ( int argc, char* argv[] )
{
std::string * program = new std::string(argv[0]); // Bad!
delete program;
}
불필요한 동적 메모리 할당이 있습니다. 이 프로그램에는 더 많은 입력 (!)이 필요하며 메모리 할당 해제를 잊어 버릴 위험이 있습니다. 명백한 이점 없이이 작업을 수행합니다.
자동 저장 장치를 최대한 자주 사용해야하는 이유
기본적으로 마지막 단락이 요약됩니다. 자동 저장 장치를 최대한 자주 사용하면 프로그램이 다음과 같이됩니다.
- 입력하는 것이 더 빠릅니다.
- 달릴 때 더 빠름;
- 메모리 / 리소스 누출이 적습니다.
보너스 포인트
참조 된 질문에는 추가 우려가 있습니다. 특히 다음과 같은 클래스가 있습니다.
class Line {
public:
Line();
~Line();
std::string* mString;
};
Line::Line() {
mString = new std::string("foo_bar");
}
Line::~Line() {
delete mString;
}
실제로 다음 것보다 사용하기가 훨씬 더 위험합니다.
class Line {
public:
Line();
std::string mString;
};
Line::Line() {
mString = "foo_bar";
// note: there is a cleaner way to write this.
}
std::string
복사 생성자 를 올바르게 정의하기 때문입니다 . 다음 프로그램을 고려하십시오.
int main ()
{
Line l1;
Line l2 = l1;
}
원래 버전을 사용 delete
하면 동일한 문자열에서 두 번 사용되므로이 프로그램이 중단 될 수 있습니다. 수정 된 버전을 사용하면 각 Line
인스턴스는 자체 문자열 인스턴스를 소유 하며 각각은 자체 메모리를 가지며 프로그램 종료시 모두 해제됩니다.
기타 노트
위의 모든 이유로 인해 RAII를 광범위하게 사용 하는 것이 C ++에서 모범 사례로 간주됩니다. 그러나 즉시 명백하지 않은 추가 이점이 있습니다. 기본적으로 부품의 합보다 낫습니다. 전체 메커니즘이 구성 됩니다. 그것은 비늘이다.
Line
클래스를 빌딩 블록으로 사용하는 경우 :
class Table
{
Line borders[4];
};
그때
int main ()
{
Table table;
}
4 개의 std::string
인스턴스, 4 개의 Line
인스턴스, 1 개의 Table
인스턴스 및 모든 문자열의 내용을 할당 하며 모든 것이 자동으로 해제 됩니다.