[디딤돌 C++] 49. 대입 연산자 중복 정의

이번에는 대입 연산자 중복 정의를 하는 방법을 살펴보기로 할게요.

대입 연산자는 개발자가 정의하지 않으면 디폴트 대입 연산자가 동작합니다. 디폴트 대입 연산자는 디폴트 복사 생성자처럼 단순히 메모리 내용을 복사하는 얕은 복사를 진행합니다. 복사 생성자처럼 클래스 내부에 동적으로 생성한 다른 개체를 갖고 있을 때 깊은 복사를 하는 대입 연산자를 중복 정의할 필요가 있습니다.

깊은 복사와 얕은 복사는 복사 생성자 부분을 다시 살펴보기기 바랍니다.

[디딤돌 C++] 16. 생성자, 소멸자

여기에서는 복사 생성자에서 예를 들었던 동적 배열을 예로 들게요. 동적 배열은 생성할 때 보관할 원소의 최대 개수를 입력 인자로 받아 배열을 동적으로 생성하게 할 거예요.

DCArray::DCArray(int _capa)
{
    Init();
    if(_capa)
    { 
        base = new int[_capa]; //bcapacity개수의 int 형식을 동적으로 생성
    }
    bcapacity = _capa;
}
void DCArray::Init()
{
    base = 0;
    bcapacity = usage = 0;
}

대입 연산자를 중복 정의하지 않으면 디폴트 대입 연산자가 동작하고 이는 디폴트 복사 생성자와 같은 문제를 발생합니다. 이에 관한 사항은 복사 생성자 부분을 살펴보세요. 이러한 문제를 해결하기 위해서는 복사 생성자처럼 대입 연산자도 깊은 복사를 수행하게 작성해야 합니다.

다음은 깊은 복사를 하는 Copy 메서드를 정의하고 복사 생성자와 대입 연사자 중복 정의한 메서드에서 이를 호출하여 문제를 해결한 것입니다.

DCArray::DCArray(const DCArray &src)
{
    Init();
    Copy(src);
}

void DCArray::Copy(const DCArray &src)//src 개체를 복사
{
    bcapacity = src.bcapacity;

    if(base)
    {
        delete[] base;
    }

    base = new int[bcapacity];
    usage = src.usage;

    for(int i = 0; i<usage;i++)
    {
        base[i] = src.base[i];
    }
}

DCArray &DCArray::operator=(const DCArray &src)//= 연산자 중복 정의    
{
    Copy(src);
    return (*this);
}

다음은 DCArr 클래스와 이를 사용하는 예제 코드입니다.

//DCArray.h
#pragma once

class DCArray
{
    int *base;
    int bcapacity;
    int usage;
public:

    DCArray(int _capa=0);
    DCArray(const DCArray &src);//복사 생성자    
    ~DCArray();//소멸자    
    void Copy(const DCArray &src);//src 개체를 복사
    DCArray &operator=(const DCArray &src);//= 연산자 중복 정의    
    void PushBack(int data);//순차 보관
    void List();//목록 출력
private:
    void Init();
};
//DCArray.cpp
#include "DCArray.h"
#include <iostream>
using namespace std;

DCArray::DCArray(int _capa)
{    
    Init();

    if(_capa)
    {        
        base = new int[_capa]; //bcapacity개수의 int 형식을 동적으로 생성        
    }    
    bcapacity = _capa;    
}

DCArray::DCArray(const DCArray &src)
{
    Init();
    Copy(src);
}

DCArray::~DCArray()
{
    if(base)
    {
        delete[] base;
    }
}

void DCArray::Copy(const DCArray &src)//src 개체를 복사
{
    bcapacity = src.bcapacity;
    if(base)
    {
        delete[] base;
    }
    base = new int[bcapacity];
    usage = src.usage;
    for(int i = 0; i<usage;i++)
    {
        base[i] = src.base[i];
    }
}
DCArray &DCArray::operator=(const DCArray &src)//= 연산자 중복 정의    
{
    Copy(src);
    return (*this);
}
void DCArray::PushBack(int data)
{
    if(usage<bcapacity)//꽉 차지 않았을 때
    {
        base[usage] = data;
        usage++;//보관 개수 1 증가
    }
}

void DCArray::List()
{
    for(int i = 0; i<usage;i++)
    {
        cout<<base[i]<<" ";
    }
    cout<<endl;
}

void DCArray::Init()
{
    base = 0;
    bcapacity = usage = 0;
}
//대입 연산자 중복 정의(깊은 복사)
//Program.cpp
#include "DCArray.h"

int main()
{
    DCArray dcarr1(10);//저장소의 크기가 10인 동적 배열 선언
    dcarr1.PushBack(4);//순차 보관

    DCArray dcarr2(dcarr1);//복사 생성으로 동적 배열 선언
    
    dcarr1.List();
    dcarr2.List();

    dcarr1.PushBack(9);
    dcarr2.PushBack(6);

    dcarr1.List();
    dcarr2.List();

    DCArray dcarr3;

    dcarr3 = dcarr1;
    dcarr1.PushBack(10);
    dcarr3.PushBack(3);
    dcarr1.List();
    dcarr3.List();

    return 0;
}

▷ 실행 결과

4

4

4 9

4 6

4 9 10

4 9 3