언어/C++

[C++] 깊은 복사와 얕은 복사

겜도리도리 2022. 3. 8. 22:49
반응형

기본 복사 생성자는 멤버 대 멤버를 복사한다. 이러한 방식은 "얕은 복사"라고 한다.

힙 영역의 메모리 공간을 참조할 때 얕은 복사의  문제가 발생한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include<iostream>
#include<cstring>
#pragma warning(disable:4996)
using namespace std;
 
class Person
{
private:
    char* name;
    int age;
 
public:
    Person(const char* myName, int myAge)
    {
        int len = strlen(myName) + 1;
        name = new char[len];
        strcpy(name, myName);
        age = myAge;
    }
 
    void ShowPersonInfo() const
    {
        cout << "이름 : " << name << endl;
        cout << "나이 : " << age << endl;
    }
 
    ~Person()
    {
        delete[]name;
        cout << "called destructor!" << endl;
    }
};
 
int main()
{
    Person man1("Sim kun woo"25);
    Person man2 = man1;
    man1.ShowPersonInfo();
    man2.ShowPersonInfo();
    return 0;
}
cs

위의 코드의 37행에서 얕은 복사가 일어난다.

그리고 main함수가 끝나면 man1과 man2의 소멸자가 호출되는데

man1에 소멸자가 호출될 때 문자열 name이 삭제된다.

이후에 man2의 소멸자가 호출되면 이미 지워진 문자열 주소를 또 지우기 때문에 다음과 같은 에러가 발생한다.

따라서 "깊은 복사"를 통해 문제를 해결해 줄 필요가 있다.

깊은 복사를 위해서는 생성자만 추가 하면 된다.

1
2
3
4
5
6
Person(const Person& other)
{
    name = new char[strlen(other.name) + 1];
    strcpy(name, other.name);
    age = other.age;}
}
cs

복사 생성자를 통해 포인터로 참조하는 대상까지 깊게 복사가 되기 때문에, 객체 마다 다른 name 저장 공간을 가지게 된다.

따라서 man1, man2 각각의 소멸자가 호출될 때, 문제가 발생하지 않는다.

문제가 해결된 것을 확인할 수 있다.

 

참고

https://bblackscene21.tistory.com/6

 

[C/C++ 공부] 깊은 복사와 얕은 복사 차이? (feat.복사 생성자)

객체를 생성하고 초기화시킬 때 멤버 변수를 어떻게 초기화하느냐에 따라 깊은 복사가 될 수 있고, 얕은 복사가 될 수 있습니다. *디폴트 생성자가 아닌 일반 생성자는 생성자의 인수를 전달 받

bblackscene21.tistory.com

 

반응형