본문 바로가기
C++

C++ 얕은 복사와 복사 생성자

by 여름코딩 2023. 2. 25.
반응형

안녕하세요 판타지코딩입니다.

 

C++에는 생성자를 통해서 새롭게 생성한 객체를 초기화하고, 그 객체를 다른 객체에 복사하여 새로운 객체를 초기화 할 수 있습니다. 이 때 복사 생성자를 호출해서 새로운 객체를 초기화하게 됩니다. 복사 생성자를 통해서 복사된 멤버 변수의 값은 동적 할당 된 멤버 변수일 경우 개발자가 임의로 동적 할당을 해주지 않으면 주소값이 복사됩니다. 이것을 바로 '얕은 복사'라고 합니다. 오늘은 얕은 복사와 디폴트 복사 생성자에 대해서 공부해 보겠습니다.

 

얕은 복사

 

얕은 복사란 동적 할당된 멤버 변수의 값을 새로운 객체에 복사했을 때 '값'이 아닌 '주소값'이 복사되는 것을 의미합니다. 

 

#include <iostream>
#include <string>

using namespace std;

class student{
public:
    int num;
    char *major;
    
    student(int nums, const char *majors)
    {
        num = nums;
        major = new char[strlen(majors)+1];
        strcpy(major, majors);
    }
    
    ~student()
    {
        delete []major;
    }
    
    void setMajor(const char *majors)
    {
        strcpy(major, majors);
    }
};

int main()
{
    student s1 = s1(1, "Education");
    student s2(s1);
    
    cout << s1.num << endl;
    cout << s1.major << endl;
    cout << s2.num << endl;
    cout << s2.major << endl;
    
    return 0;
}

얕은 복사를 수행한 예제를 작성했습니다. student 클래스는 학번 정보를 담은 int형 변수 num과 전공 정보를 담은 char *major를 갖고 있습니다. major는 동적 할당을 한 변수이기 때문에 초기화 과정이 num과 다른 부분이 있습니다.

 

student(int nums, const char *majors)
{
    num = nums;
    major = new char[strlen(majors)+1];
    strcpy(major, majors);
}

 

student 생성자는 인자로 nums와 majors값을 받아서 num과 major에 저장합니다. nums는 int형 변수이므로 num에 그대로 저장하지만, major는 동적 할당을 하므로 먼저 new char[strlen(majors)+1] 를 통해서 데이터를 저장할 메모리를 할당해줍니다. 그리고 strcpy를 통해서 major에 majors를 저장해줍니다.

 

생성자를 활용해서 s1 객체를 먼저 생성해 보겠습니다.

 

student s1 = s1(1, "Education");
student s2(s1);

 

student 객체 s1를 생성할 때 num에 1을, major에 "Education"을 저장합니다. 그리고 student 객체 s2를 생성하면서 s1을 복사해서 s2에 저장합니다. 이렇게 하면 s1의 멤버 변수가 s2의 멤버 변수에 복사됩니다. 이 때 호출되는 것이 바로 '디폴트 복사 생성자'입니다.

 

1
Education
1
Ecucation

코드 실행 결과 s1과 s2에는 같은 값이 저장되어 있으므로 위와 같은 결과가 출력됩니다.

 

s1의 num이 s2의 num에 저장되고, s1의 major가 s2의 major에 저장되었습니다. 하지만 major는 동적 할당한 배열이므로 '주소값'이 s2의 major에 저장됩니다. 그러므로 s1과 s2는 major의 주소값을 공유한 것입니다! 아래의 그림을 참고하시면 되겠습니다.

 

 

 

s1과 s2가 major의 주소값을 공유한다면 한 쪽에서 major 값을 변경하면 다른 쪽도 값이 변경될 것입니다.

 

s2.num = 2;
s2.setMajor("language");

cout << s1.num << endl;
cout << s1.major << endl;

cout << s2.num << endl;
cout << s2.major << endl;

 

s2의 num에 2를 저장하고, s2의 major는 "language"로 변경했습니다.

 

1
language
2
language

 

먼저 s1의 num값은 그대로 1입니다. 그리고 major의 값은 s2의 major의 값을 "language"로 변경하면서 s1의 major 값 또한 동일하게 출력되었습니다. 그러므로 s1과 s2는 major의 주소값을 공유함을 알 수 있습니다.

 

그럼 오늘은 얕은 복사와 디폴트 복사 생성자에 대해서 공부해 보았습니다.

 

감사합니다!

반응형