소멸자와 복사 생성자

김펭귄·2025년 5월 5일

C++

목록 보기
17/20

1. 소멸자 (Destructor)

  • 객체 소멸 시 리소스(메모리) 정리 담당
  • 함수가 종료되어 지역 변수인 객체가 정리되거나, 동적으로 할당한 객체 메모리를 다시 delete 해줄 때 등 객체가 사라지는 경우에 소멸자가 호출된다
  • 객체 소멸시킬 때 원하는 동작을 구현해주면 됨
  • 특징
    • ~클래스명() 형태
    • 매개변수 없음, 오버로딩 불가
    • 동적 할당 메모리, 파일 핸들, 네트워크 연결 등 정리에 필수
  class Student {
      char* name;  // 동적 할당
  public:
  	  Student() {name = new char[5]; strcpy(name, "KIM");}
      ~Student() { delete[] name; }  // 메모리 누수 방지
  };
  • 소멸자를 정의하지 않으면 컴파일러가 default destructor 생성

2. 기본 소멸자(Default Destructor)

  • 단순히 상속된 객체의 메모리를 정리

  • 직접 소멸자를 정의하지 않아도 되기에 편함

  • 그러나, 동적 메모리, 파일 핸들, 네트워크 등 외부 자원을 직접 해제하지 않음

  • 이런 경우 직접 소멸자를 정의하여 사용


3. 복사 생성자 (Copy Constructor)

  • 같은 클래스의 다른 객체를 인자로 받아, 그 객체를 복사하여 새로운 객체를 생성하는 특별한 생성자
  • ClassName(const ClassName& other);
class T {
privae:
	int id;
public:
	T(const T& x) {  // 복사 생성자
    	id = x.id;	 // &로 private인 id 변수에 접근 가능
    }	
};
  • const를 사용하여 인자로 받은 객체를 수정하지 않게 함
  • &을 통해 인자로 받은 객체에 쉽게 접근

4. 복사 생성자 호출

  • 객체를 다른 객체로 초기화할 때
   Book b1("C++", 300);	// 생성자 호출
   Book b2 = b1; // 복사 생성자 호출
   Book b3(b2);  // 복사 생성자 호출. 둘 다 같은 방식이다
  • 함수에 객체를 값으로 전달할 때
   void func(Book b); 
   func(b1);	// 복사 생성자 호출하여 b에 b1이 복사됨
  • 함수가 객체를 값으로 반환할 때
   Book func() { Book b; return b; }
   Book b2 = func(); // 반환값 복사   
  • 단, 함수가 객체를 값으로 반환할 때의 경우, 최근 컴파일러는 복사생성자 대신 RVO나 이동생성자로 객체를 생성하기도 함

5. 디폴트 복사 생성자

  • 복사 생성자를 정의하지 않으면, 컴파일러가 자동으로 "디폴트 복사 생성자" 생성

  • 디폴트 복사 생성자는 모든 멤버를 1:1로 얕은 복사함


6. 깊은 복사와 얕은 복사

  • 얕은 복사(Shallow Copy)

    • 멤버 변수 값을 그대로 복사
    • 포인터 멤버변수도 마찬가지므로 주소만 복사 → 두 객체가 같은 메모리를 가리킴
    • 이 경우 두 객체를 제거할 경우, 같은 메모리를 가리키기에 동일한 주소에 2번 제거가 일어남 -> 에러
    • 또한, 하나의 객체만 수정해도 데이터 공유로 다른 객체도 수정되는 문제
  • 깊은 복사(Deep Copy)

    • 포인터 멤버가 참조하는 실제 데이터까지 다른 메모리에 새로 복사
    • 두 객체가 완전히 독립적으로 동작함
    • 따라서 포인터 멤버가 있다면 깊은 복사로 구현해야 함

profile
반갑습니다

0개의 댓글