본문 바로가기
[공부]/C++

[C++] 기본 정리 14 - 생성자, 복사 생성자, 소멸자

by 개발꿈냥무 2024. 2. 24.

멤버 변수의 초기화

- 객체를 생성하면 메모리에 즉시 생성되지만, 모든 멤버 변수를 초기화하기 전까지 사용할 수 없음

- 일반적인 초기화 방식으로 초기화할 수 없음 (private 멤버에는 직접 접근할 수 없기 때문)

  -> private 멤버에 접근할 수 있는, 초기화만을 위한 public 함수가 필요!

 


생성자 (constructor)

  • 객체의 생성과 동시에 멤버 변수를 초기화해주는 멤버 함수
  • 클래스 생성자의 이름은 해당 클래스의 이름과 같음

 

생성자 특징

  1. 초기화를 위한 데이터를 인수로 전달받을 수 있음
  2. 반환값이 없지만, void형으로 선언하지는 않음
  3. 객체를 초기화하는 방법이 여러 개 존재할 경우, overloading 규칙에 따라 여러 개의 생성자를 가질 수 있음

 

생성자 선언

생성자 원형 예)
Book(const string& title, int total_page);

생성자 선언 예)
Book::Book(const string& title, int total_page) {
	title_ = title;
	total_page_ = total_page;
	set_percent();
	...
}

 

 

생성자 호출

C++에선 클래스에서

  • 객체를 생성할 때마다 해당 클래스의 생성자가 컴파일러에 의해 자동으로 호출됨
  • 사용자가 직접 생성자를 명시적으로 호출할 수도 있음
객체 생성하면서 생성자가 암시적으로 호출되는 예)
int main() {
	Book web_book("HTML과 CSS", 350); // 생성자의 암시적 호출
    // 생성자가 호출되어 멤버 변수인 percent_가 초기화되었는지 확인
    cout << web_book.percent_;
}

void Book::set_percent() {
	percent_ = (double) current_page_ / total_page_ * 100;
}

 

 

 


디폴트 생성자

  • 객체가 생성될 때 사용자가 초깃값을 명시하지 않으면, 컴파일러가 자동으로 제공하는 생성자
  • 클래스에 생성자가 단 하나도 정의되지 않았을 때만! 컴파일러가 자동 제공 (아니면 초깃값 없이 객체를 선언하면 오류 발생)
  • 인수를 전달받지 않으므로, 매개변수를 갖지 않음
  • 대부분의 디폴트 생성자가 0이나 NULL, 빈 문자열 등으로 초기화 진행

 

디폴트 생성자의 정의 (사용자가 직접)

 1. 함수 오버로딩을 이용

 2. 디폴트 인수를 이용 : 기존 생성자의 모든 인수에 디폴트 인수를 명시

(클래스는 단 하나의 디폴트 생성자를 가질 수 있으므로, 둘 중 하나의 방법만 사용해야 함)

1) 함수 오버로딩 예
Book();

2) 디폴트 인수 예
Book::Book(const string& title = "웹 프로그래밍", int total_page = "100");

 

 

디폴트 생성자를 갖는 객체의 선언

1) Book web_book; // 디폴트 생성자의 암시적 호출
2) Book web_book = Book(); // 디폴트 생성자의 명시적 호출
3) Book *ptr_book = new Book; // 디폴트 생성자의 암시적 호출

오류) Book web_book(); // 컴파일러가 객체 선언이 아닌 함수의 호출로 보게 되므로 오류 발생

 

 


얕은 복사 (shallow copy)

  • 값을 복사하지 않고, 값을 가리키는 포인터를 복사! (즉, 주소값을 복사한다는 의미)
  • 복사하는 대상과 참조하고 있는 실제 값은 같음
  • 대입 연산자( = )를 이용한 객체의 대입에서 수행됨
  • 변수의 생성에서 얕은 복사는 문제되지 않지만, 객체의 생성에서는 문제가 발생할 수도 있음 (특히 객체가 메모리의 힙(heap) 영역을 참조할 경우)

깊은 복사 (deep copy)

  • '실제 값'을 복사
  • 복사 생성자를 재정의해서 원하는 멤버 변수만 복사해주는 방법을 사용
  • 복사 생성자에서는 const로 인자를 받아서 기존 객체의 멤버 변수를 변경할 수 없도록 하기를 권장

복사 생성자 (copy constructor)

  • 자신과 같은 클래스 타입의 다른 객체에 대한 참조(reference)를 인수로 전달받아, 그걸 이용해 자신을 초기화
  • 새롭게 생성되는 객체가 원본 객체와 같으면서도, 완전한 독립성을 갖게 해줌
  • 깊은 복사에 해당됨

 

복사 생성자를 사용하는 주요 상황

  1. 객체가 함수에 인수로 전달될 때
  2. 함수가 객체를 반환할 때
  3. 새로운 객체를 같은 클래스 타입의 기존 객체와 똑같이 초기화할 때
복사 생성자 선언 예)
Book::Book(const Book& origin) {
	title_ = origin.title_;
	total_page_ = origin.total_page_;
	...
}

복사 생성자 활용 예)
Book web_book("HTML", 300);
Book html_book(web_book); // 복사 생성자를 이용해, 새롭게 생성되는 html_book 객체를 web_book 객체로 초기화
->컴파일러에 의해 다음과 가은 복사 생성자를 사용한 것으로 해석됨
-> Book html_book = Book(web_book);

 

 

 


소멸자 (destructor)

  • 객체 수명이 끝나면, 생성자의 반대 역할을 수행하는 멤버 함수
  • 객체 수명 끝나면 컴파일러가 자동으로 호출하여 사용이 끝난 객체를 정리해 줌 (그 외에는 수행할 작업이 없음)
  • 클래스 소멸자의 이름은 해당 클래스의 이름과 같고, 이름 앞에 물결 표시(~)를 붙여 생성자와 구분함

 

소멸자의 특징

  1. 인수를 갖지 않음
  2. 반환값이 없지만, void형으로 선언하지 않음
  3. 클래스는 소멸자를 단 하나만 가질 수 있음 (생성자는 여러 개 가능)
  4. const, volatile, static으로 선언될 수 없지만, const, volatile, static으로 선언된 객체의 소멸을 위해서 호출은 가능
  5. 소멸자의 원형은 클래스 선언의 public에 포함되어야 함
소멸자 원형 예)
~Book();

소멸자 선언 예)
Book::~Book() {
	// 프로그램 종료 시 컴파일러에 의해 자동으로 호출됨
	cout << "Book 객체의 소멸자가 호출되었습니다.\n";
}

 

 

소멸자의 호출

C++에서 소멸자의 호출 시기는 컴파일러가 알아서 정함

  • 메모리의 데이터 영역 : 해당 프로그램이 종료될 때
  • 메모리의 스택 영역 : 해당 객체가 정의된 블록을 벗어날 때
  • 메모리의 힙 영역 : delete를 사용하여 해당 객체의 메모리를 반환할 때
  • 임시 객체 : 임시 객체의 사용을 마쳤을 때

 

 


참고)

코딩의 시작, TCP School

 

코딩교육 티씨피스쿨

4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등

tcpschool.com