본문 바로가기

PL/C & C++

[C++] 복사 생성자와 delete 키워드

복사 생성자

문제점

 

실행 시 얕은 복사(shallow copy)에 의한 메모리 참조 에러 발생

 

  • 객체 p1 선언 시 생성자에서 name, phone 메모리 할당
  • 객체 p2 선언 시 디폴트 복사 생성자에서 메모리 할당 없이 객체 p1의 name, phone의 포인터만 복사(얕은 복사)
  •  p2 소멸자 호출하여 name, phone 포인터가 가리키는 메모리 해제

소멸자 호출 순서는 생성자와 반대 순서

p1 소멸자 호출하여 name, phone 포인터가 가리키는 메모리 해제 시 실행 에러

이미 p2 소멸자에 의해 해제 !!!

얕은 복사

 

 

™ 메모리를 할당하는 깊은 복사를 하는 생성자를 작성하여 해결

 

깊은 복사

 

<delete>

 

C++11 이전엔 private 안에 복사 생성자와 대입 연산자를 정의하여 외부에서 접근하지 못하게 하는 방법 이였다면, 

이젠 delete 키워드를 통하여 특정 함수에 대한 정의를 금지할 수 있습니다.

 

 


 

 

delete 키워드를 사용하여 삭제하기

다음 방법은 delete 키워드를 사용하여 함수를 명시적으로 삭제하는 방법 입니다.

 

 

이렇게 delete 키워드를 사용하여 복사생성자를 삭제하고 삭제된 함수를 정의하거나 호출하게 되면 컴파일 과정에서 error를 발생시키케 됩니다.

 

 

복사 생성자가 호출되는 시점

1. 기존에 생성된 객체를 이용해서 새로운 객체를 초기화하는 경우

 

파란색 글씨에서 복사생성자의 호출이 이루어진다.

init과 set이 끝난 C1 class 객체를 C2 class 객체에서 복사생성자를 호출하여 복사하고 있는 형태이다.

 

 

2. 함수의 인자로 call by value 형태로 인자를 받는 경우

 

C/C++은 call by value 기반의 언어이기 때문에 인자를 레퍼런스가 아닌 형태로 받을 경우 무조건 임시 변수를 생성하여 메모리를 잡고 그 임시 변수에 인자로 받은 값을 call by value 형태로 복사한 뒤 사용한다.

따라서 함수의 인자로 객체를 받을 경우 위 코드의 파란색 부분에서 C_DATA class의 임시 객체를 생성하고 바로 인자를 복사생성자에 의해서 값을 복사하게 된다.

 

3. 함수의 반환 형태가 call by value 형태로 반환하는 경우

 

 

2번째 내용과 비슷하게 반환 형식을 레퍼런스가 아닌 형태로 반환할 경우 임시 변수를 생성해 메모리를 잡고 거기에 반환할 값을 복사한 뒤 그 임시 변수를 반환하게 된다.

따라서 위의 코드에서 파란색 부분처럼 객체를 반환하게 될 경우 반환 과정에서 C_DATA라는 임시 객체를 생성하고 반환하는 c1 객체를 복사생성자를 통해 복사한 뒤 반환하게 됩니다.

 

 

복사 생성자의 호출을 막는 이유

프로그래머가 class를 구현하는 경우 default 생성자만 구현하여 단순히 멤버 변수를 초기화 하는 기능만 추가합니다. 따로 동적할당과 같은 기능이 필요하다면 init 함수를 따로 구현하여 사용자가 그 함수를 호출하게 하는 것이 좋습니다.

class가는 모듈을 call by value의 형태로(얕은 복사와 깊은 복사 모두) 복사를 하게 되면 프로그래머가 의도와 다르게 사용이 가능하게 되고 또 많은 리소스를 사용하게 되어 비효율적입니다. 또 중요한 것은 class라는 모듈에 무엇이 들어있는지도 모르면서 복사를 하는 것은 굉장히 좋지 않습니다. 

따라서 프로그래머는 본인이든 사용자든 이러한 복사 기능을 사용하지 못하게 막아야 합니다. 그리고 필요한 값이 있다면 get으로 시작하는 함수를 구현하여 값을 사용하는 것이 바람직합니다.

 

 

 

[C++]복사 생성자와 delete 키워드

C++ 클래스에는 프로그래머가 직접 구현하지 않아도 생성되는 생성자들이 있는데 그 중 하나가 바로 복사 생성자 입니다. 이름과 동일하게 복사 생성자는 class 변수에 다른 변수의 값을 복사하는

junk-s.tistory.com

 

'PL > C & C++' 카테고리의 다른 글

[C++] string 관련 함수  (0) 2021.02.24
[C] strnset 부분 문자열을 특정 문자로 채우기  (0) 2021.02.24
[C++] 생성자 개괄- explicit, delete, default, override  (0) 2021.01.27
[C++] 상속  (0) 2021.01.27
[C++] 소멸자(destructor)  (0) 2021.01.27