본문 바로가기
c++

복사 연산자를 만들때 주의해야 할점을 알아보자.

by chunma1126 2025. 2. 5.

 

 

cpp에서 복사 연산자를 만들때 주의해야할것들이 있다.

자기 대입 검사

복사연산을 할때 자기자신에 대입을 하는건 아닌지 검사가 필요하다.

직관적으로 이해하기 어렵기 때문에 예제 코드를 통해 설명 하도록 하겠다.

class MyClass 
{
public:
    int* ptr;

    MyClass& operator=(const MyClass& other)
    {
        delete ptr;
        ptr = other.ptr;

        return *this;
    }
};

int main() 
{
    MyClass a;
    
    a = a;

    std::cout << a.ptr;

    return 0;
}

 

MyClass는 복사 연산을 할때 기존에 ptr을 지우고 새로운 ptr을 받는다.

근데 자기자신을 복사하고 있기 때문에 a에 ptr을 지우고 a에 방금 지운 ptr을 넣으려고 하기 때문에 오류가 난다.

 

때문에 다음과 같은 문제를 해결하기 위해 딱 한줄만 추가하면 된다.

class MyClass 
{
public:
    int* ptr;

    MyClass& operator=(const MyClass& other)
    {
        if (this == &other)
            return *this;

        delete ptr;
        ptr = other.ptr;

        return *this;
    }
};

이 한줄만 추가하면 자기 대입을 검사할수 있다.

 

예외 안전성

복사 연산 중에 문제가 생길 수 있으니 먼저 다른 객체의 내용을 복사해서 임시 사본을 만든 다음 문제가 없다면 이 사본과 현재 객체의 내용을 서로 바꿔(swap) 교환하는 방식이다.

이렇게 하면 복사하는 동안 에러가 나면 원래의 데이터는 그대로 유지되고 에러 없이 복사가 잘 되면 안전하게 새로운 데이터로 바꿀 수 있다.

 

간단하게 예를 들어보자면

 

 

친구의 장난감 상자를 복사한다. (임시 복사본을 만든다.)

복사가 성공하면, 내 장난감 상자와 복사본을 교환한다. (swap)

복사 과정에서 문제가 생기면, 내 장난감 상자는 그대로 유지된다.

 

이렇게 진행을 하면 예외에 대한 안전성이 강화된다.

 

#include <iostream>
#include <algorithm>

class MyClass {
public:
    int* ptr;
public:
    MyClass(int value) 
    {
        *ptr = value; 
    }
    MyClass(const MyClass& other)
    { 
        ptr = new int(*other.ptr);
    }

    MyClass& operator=(MyClass other) {
        std::swap(ptr, other.ptr);
        return *this;
    }
    
};

int main()
{
    MyClass a(10), b(20);
    a = b;
    
}

 

다음 코드는 예외 안전성을 챙긴 코드이다.