오늘은 깊은 복사 / 얕은 복사, C++ 메모리 구조, 동적할당에 대한 수업을 진행하였다.
1. 깊은 복사 / 얕은 복사
깊은 복사와 얕은 복사는 클래스 멤버에 포인터가 존재할 때 사용하는 용어이기에 포인터가 없다면 단순히 복사라고 생각해도 무방하다.
- 얕은 복사 - 클래스의 외형을 그대로 복사한다.
포인터의 경우 참조하는 메모리를 복사하지 않아 원본과 복사본이 동일한 메모리를 공유하게 된다.
즉, 클래스에 눈에 보이는 것만 복사를 한다. - 깊은 복사 - 클래스가 가진 모든 구조와 메모리를 동일하게 만들어서 복사한다.
포인터의 경우 참조하는 대상까지 복사하여 독립된 메모리를 가지게 된다.
즉, 클래스에 눈에 보이지 않는 것까지 전부 복사를 한다. - 지금 현재 Class에 가지고 있는 구조, 메모리 등등 전부를 똑같이 만들어 복사를 하는 것
(포인터의 경우 포인터의 참조까지 전부 복사를 하기에 다른 메모리를 가짐 )
즉, Class에 눈에 보이지 않는 것까지 전부 복사를 한다.
이게 좀 찾아보면 얕은 복사는 잘못된 복사라고 하는데, 자신이 의도적으로 공유메모리를 가지게 설계를 했다면 문제가 전혀 없다. 그렇기에 얕은 복사가 잘못된 복사라는 말은 틀린 말이 되는 것이고, 애초에 본질적으로 Class를 복사를 하면 안 된다.
2. C++ 메모리 구조 ( 중요 )
- Code 영역 : 프로그램의 코드가 저장되는 영역으로 CPU는 코드 영역에 저장된 명령어를 하나씩 가져가 처리한다.
- Data 영역 : 프로그램의 전역변수와 정적(static) 변수가 저장되는 영역이며, 프로그램의 시작과 함께 할당되며, 프로그램이 종료하면 소멸한다. ( 전역변수는 관리하기 힘들어 거의 안 쓰인다 )
- Stack 영역 : 함수의 호출과 관계되는 지역변수와 매개변수(함수)가 저장되는 영역이다. 스택영역은 함수의 호출과 함께 할당되며, 함수의 호출이 완료되면 소멸한다. 이렇게 스택에 저장되는 함수의 호출 정보를 스택 프레임이라 한다. 스택영역은 메모리의 높은 주소에서 낮은 주소의 방향으로 할당된다.
- Heap 영역 : 사용자가 직접 관리할 수 있는 메모리 영역이다. 사용자에 의해 메모리 공간이 동적으로 할당되고 해제됩니다. 힙영역은 메모리의 낮은 주소에서 높은 주소의 방향으로 할당된다.
2.1 스택 프레임
함수가 호출되면 스택에는 함수의 매개변수, 반환 주소, 함수 내 지역 변수가 저장되는데, 이 정보를 스택 프레임이라 한다. 이를 통해 함수가 끝난 후 호출 이전의 상태로 되돌아갈 수 있다..
스택 프레임에서 변수는 미리 할당된 일정 메모리 (1MB) 내에서 동적으로 할당 및 해제되며, 지역변수 및 매개변수의 메모리 할당 속도가 느리기 때문에 이러한 방식으로 관리된다.
3. 동적할당 (Dynamic Programming)
3.1 정의
- 프로그램이 실행되는 도중 (런타임), 실행에 필요한 메모리를 기억하여 할당하는 기법이다.
3.2 동적할당 사용법
C언어에서는 malloc이라는 걸 주로 사용을 했을 것이다. 하지만 C++에서는 malloc을 사용하면 안 된다. 이유를 봐보자
malloc은 바이트 단위로 사이즈를 잡기 때문에 Class 기반의 문법이 아니기에 생성자가 불리지 않게 된다.
C++은 Class 기반 언어이기에 상호 소통을 원칙으로 코딩을 해야 하는데 이런 원칙을 다 무시하기에 사용하면 안 된다.
그럼 어떤 걸 사용해야 할까? 바로 new , delete이다.
예시를 봐보자
#include <iostream>
int main()
{
int* p{}; // 기본 생성자 호출
// p = new int(20); // 복사 생성자 호출
p = new int{};
printf("%d", *p);
delete p;
}
- new는 클래스를 기반으로 메모리를 할당하므로 생성자가 호출되며, malloc처럼 단순한 메모리 블록을 할당하는 것이 아니다.
- 래퍼런스가 아닌 포인터가 따라붙어야 하며, () 대신 {}를 사용하여 청소를 진행하자 ( ()도 사용가능하지만 통일성을 위해 {}를 사용할 것)
- new에서 메모리를 잡아주지 않는다면 코드의 문제가 아닌 컴퓨터의 문제이기에 알아두자
- delete는 동적 할당된 메모리를 해제하여 메모리 누수를 방지한다.
3.3 메모리 누수
정의 : 필요 없는 메모리를 해제하지 않아 계속 점유되는 현상
이게 만약 메모리를 계속 점유하고 있는 경우 솔직히 문제가 그렇게 되지는 않는다. 하지만 메모리 누수가 계속 누적이 되면 문제가 발생한다.
즉, 중요한 부분은 메모리 누수가 누적이 되는 것이라는 것이다.
3.4 동적할당 주의점
- 동적 할당은 메모리 할당 속도가 느리기 때문에 함수 내의 지역변수로 처리할 수 있는 부분은 동적 할당을 피하는 것이 좋다.
- 진정으로 필요한 경우나 속도가 보장되어야 하는 상황에서만 동적 할당을 하자.
'C++' 카테고리의 다른 글
[강의] 11월 1일 수업정리 (0) | 2024.11.03 |
---|---|
[강의] 10월 31일 수업정리 (2) | 2024.11.01 |
[강의] 10월 29일 수업정리 (1) | 2024.10.29 |
[강의] 10월 25일 수업정리 (0) | 2024.10.27 |
[강의] 10월 24일 수업정리 (0) | 2024.10.25 |