본문 바로가기

CS/C++

[C++]복사생성자(Copy Constructor)

728x90

복사 생성자(Copy Constructor)는 같은 형태의 객체를 인자로 전달하는 생성자입니다.

C++에서는 변수 초기화 방법이 2가지가 있습니다.


1
2
3
int A = 5;//방법1
int B(3);//방법2
cout << A << " : " << B << endl;
cs


변수를 초기화 하는 방식에 객체를 넣어서 초기화를 해도 정상적으로 동작합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;
class myClass{
    private:
        int num1;
    public:
        myClass(int _num){
            num1 = _num;
        }
        void print(){
            cout << "num1 : " << num1 << endl;
        }
};
 
int main(int argc, char** argv) {
    myClass myC(2);
    myClass myA(myC);
    myA.print();
    return 0;
}
 
cs


출력결과

num : 2 


동작과정

num1 값이 2인 myClass 객체인 myC를 생성한다. 

-> myC값의 멤버값인 num1와 같은 값을 가지는 myA를 생성한다. 

-> myA.print()에서 myC에서 받은 num1값이 출력된다.


위 코드는 잘 동작하는 것 같아 보입니다. 

만약 아래 처럼 멤버변수가 포인터를 사용하면 문제가 발생한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
using namespace std;
class myClass{
    private:
        int *ptr;
    public:
        myClass(int _num){
            ptr = new int;
            *ptr = _num;
        }
        ~myClass(){
            delete ptr;
        }
        void print(){
            cout << "ptr : " << *ptr << endl;
        }
};
 
int main(int argc, char** argv) {
    myClass myC(2);
    myClass myA(myC);
    myC.print();
    return 0;
}
cs

myC는 멤버변수로 ptr이라는 포인터 값을 가지는 클래스입니다. myA의 멤버변수 ptr은 myC를 복사하였기 때문에 같은 포인터 값을 가지게 된다.

그림으로 표현하면 아래와 같습니다.


얕은복사(Shwallow Copy)




코드가 모두 종료하면 할당한 객체들을 소멸자를 이용해서 메모리상에서 제거하는 작업을 진행하는데 myC와 myA는 같은 포인터를 가지기 때문에 포인터 제거작업이 2번 진행됩니다. 그렇게 되면 시스템은 오류를 출력하게 됩니다.


이러한 상황은 복사작업이 단순히 값을 복사하는 얕은 복사(Shwallow Copy)이기 때문에 발생합니다.

우리는 깊은 복사(Deep Copy)를 이용해서 겉보기에 같은 값들을 가져 보이게 하는것이 아닌, 완전히 똑같은 값을 가지지만 별개의 객체를 만드는 작업을 진행해야 합니다.

깊은복사(Deep Copy)

깊은 복사를 위해선 복사생성자를 직접 작성해야합니다. 클래스 내부에 아래와 같은 복사 생성자를 작성합니다.
1
2
3
4
myClass(const myClass &obj){
            ptr = new int;
            *ptr = *obj.ptr;
}
cs
복사생성자는 같은 형태의 객체의 레퍼런스를 인자로 받는 생성자입니다. 인자로 받은 객체의 멤버변수의 값을 복사되는 객체의 멤버변수로 선언합니다.
여기서 const로 선언하는 이유는 인자로 보낸 객체의 값이 변경되는 것을 막기 위해 사용됩니다. 없어도 동작은 합니다.



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

[C++]템플릿(template)  (0) 2016.06.07
[C++]다형성(Polymorphism)  (0) 2016.06.07
[C++]상속 접근 지시자  (0) 2016.06.07
[C++] 다중상속(Multiple inheritance)  (0) 2016.06.07