본문 바로가기
C++

복사생성자

by 상레알 2009. 1. 8.

의미
필요성
정의


int val1= 20;     <- C 스타일 초기화 
int val1(20);    <-  C++ 스타일의 초기화

위의 두개의 코드는 같은 코드이다 두번쨰 int val1(20)을 보면 마치 객체 생성 문법처럼 보인다 C++은 두가지 형태의 초기화
 방법을 제고하고 있다.

객체도 이와 같이 할수잇다.

AAA a2= 20;     AAA a2(20);  
               
하지만 위 두개의 소스가 완전하게 같은것은 아니다 왜냐하면  AAA a2=20; 이 소스는 묵시적으로 변환이 이루어지는 것이다

AAA a2= 20; ===>(묵시적인 변환)    AAA a2(20);  

보통 결과적으로는 같으나 차이를 보이는 경우도 잇다 자세한것은    explicit 를 공부하면서 다시 이야기 하겟다고한다.-_-

Point (const Point&p)     <-  디폴트 복사생성자의 형태
{ }

- 복사 생성자도 생성자 이므로 함수의 이름이 클래스명과 동일해야되며 복사 생성자 호출시 이미 존재하는 객체를 전달 인자로 주므로 이를 형식인수가 레퍼런스 변수로 받아 처리한다. 레퍼러스란 이미 선언도니 객체를 별명으로 불러서 사용하는 개념
별명으로 원래의 객체를 변경하면 안되므로 앞에 const 키워드를 덧붙인다.. const는 상수라는 의미를 내포하고 있는 지정어로 별명이 가리키는 객체의 값을 가져다 사용만 할 뿐  변경하지 못하도록 하기위해서 사용한다.

복사생성자는 자기 자신과 같은 형태의(자료형의) 객체를 인자로 받을 수있는 생서자를 복사 생성자라고 하는것이다.그리고 멤버 변수 값만 복사 한다.(만약 동적 메모리 할당 햇을시...생성자에서 동적 메모리 할당한것까지는 복사생성자가 인식하지 못한다 그러므로 이럴경우 복사 생성자를 재정의해서 동적 메모리 할당하는 것을 기술하여야 된다.)
복사 생성자를 보면 매개변수 선언에서 const가 붙어 있음을 볼 수 있다. - 인자로 전달된 객체의 내용의 변경을 허용하지 않겟다는 선언이다. 전달되는 인자를 레퍼런스로 받기 때문에 const 선언을 하지 않으면, 내용 변경이 가능할 것이다. 그렇다면 & 선언은  - 인자로 전달된 객체를 레퍼런스로 받겟다는 선언이다.
- 복사생성자에서 전달 인자 선언에서 const 선언은 해주지 않아도 상관없다. 그러나 &선언은 반드시 해줘야 한다. *****
***이유는 &선언이 없다면 무한루프에 빠져 버리기 떄문이다. 컴파일러에서는 &선언을 하지 않는다면 컴파일 오류를 발생시켜준다.
-?? ㅇ왜왜왜 무한루프에 빠지지;;;-_ㅠ

클래스를 정의하는데 있어서 프로그래머가 정의해 주지 않으면 알아서 자동으로 삽입되는 것 은 4가지가 잇는대  디폴트 생성자 와 디폴트 소멸자 그리고 디폴트 복사 생성자,  연산자 오버로딩이 있다!

디폴트 복사 생성자의 기능은 멤버 대 멤버를 복사하는것이다. 그리고 클래스마다 정의되어 들어가는 디폴트 복사생성자의 형태는 다르다   

-디폴트 복사 생성자의 문제 -

디폴트 복사생성자는 멤버 변수다 멤버 변수의 복사이다. 그렇다면 멤버 변수가 포인터로 선언이 되어잇다면

과연  포인터 멤버변수가 가르키고 있는 값을 복사 하나....아님 주소값을 복사 할까?

이처럼 이들이 지니고 있는 그값은 문자열이 아니라 문자열을 가리키는 주소값이다 . 이를 가르켜서 얕은 복사라  한다.

그리고 문제는 여기서 부터 시작된다.

객체로 선언된것은 언젠가는 소멸이 될것이다. 그렇다면 주소값을 복사해 갓다면 같은 값을 2개의 포인터가 가리키게 되는대

예를 들어    person p2(p1 )   ==   person p2=p1   는 같은 말이다.

위 클래스의 멤버 변수가 포인터로 선언이 되어 있다면  p1 객체가 가리키는 값과 p2가 가르키는 값이 같게 되는대 p1과 p2 는

언젠가는 소멸될것이고 그러기 위해서 p1이 지니는 소멸자와 p2가 지니는 소멸자가 각각 호출될 것이다.  소멸되는 순서는

객체의 생성과 반대를 이룬다 즉.  p2가 소멸이 되고 그다음에 p1이 소멸이 되는대 p2가 소멸이 될떄 p1의 객체랑 같이 가르키

고 있던값도 소멸 시켜버린다. 그리고 나서 p1이 지니고 있는 소멸자가 소멸 되는대 이 소멸자 역시 가리키고 잇던 값과 멤버

변수를 해체하려고 할것이다. 그런대 문제는 가리키고 있던 값이 p2 객체 소멸시에 벌써 해체가 되었기 떄문에  더이상 해체할
메모리 공간이 없기에 문제가 된다.

이 문제의 해결책은 디폴트 복사 생성자는 얕은 복사를 하므로 깊은 복사를 하도록 프로그래머가 직접 복사 생성자를 제공하면 된다.

+_+ -=  생성자 내에서 동적 할당을 하면, 반드시 제공해야 하는것이 무언이냐 하면 소멸자이다 그래야 메모리 누수(유출)이 발생하지 않는다. 뿐만 아니라 복사 생성자도 정의해야 한다. 그래야 잘못된 메모리 참조를 막을 수 있다.


그리고 만약 상속을 할경우에는 Derived 클래스에서 Base 클래스에 대한 부분도 고려해야된다!!!

'C++' 카테고리의 다른 글

상속!!  (0) 2009.01.15
explicit &&&& mutable  (0) 2009.01.15
클래스와 Static  (0) 2009.01.15
클래스와 const  (0) 2009.01.14
복사 생성자가 호출되는 시점  (0) 2009.01.08
const 함수  (0) 2009.01.06
friend 선언  (0) 2009.01.06
This 포인터  (0) 2009.01.06
열혈강의 연습문제 4-2 /생성자/소멸자/객체 포인터 동적 할당/해체/문자입력받아서 순서대로 출력  (0) 2009.01.06
malloc 함수와 new 연산자의 차이  (0) 2009.01.05