본문 바로가기

C++

[C++] operator 대입연산자

변수뿐만 아니라 클래스나 구조체에서도 단순 대입 연산이 이루어질 수 있다.

 

#include <iostream>
using namespace std;

class TestClass
{
public:
	TestClass() {}
	TestClass(int param)
	{
		num = new int;
		*num = param;
	}

	TestClass(const TestClass& ref)
	{
		num = new int;
		*num = *ref.num;
	}

	~TestClass() { delete num; }

	int getNum()
	{
		return *num;
	}

private:
	int *num = nullptr;
};

int main()
{
	TestClass a(10);
	TestClass b(20);

	a = b;	//에러

	cout << a.getNum() << endl;

	return 0;
}

 

결과값:

에러, 프로그램종료

 

에러가 발생한 이유는 a=b 때문이다. 단순 대입 연산자는 얕은 복사가 이루어진다. 이로 인해 이미 해제한 메모리를 또 해제하면서 에러가 발생한다. 해결방법은 단순 대입 연산자 함수를 정의하는 것이다.

 

 

TestClass& operator=(const TestClass& ref)
{
    //기존 가리키던 메모리 삭제
    delete num;
    
    //새로 할당 후 대입
    num = new int(*ref.num);
    
    return *this;
}

 

TestClass안에 위 내용을 추가하면 에러가 발생하지 않는다.함수 이름이 'operator='이고 깊은 복사가 이루어지도록 정의하였다.(operator+ 같은 것도 있다) 리턴값은 void를 반환해도 상관없으나 void 반환 시 a = b = c; 혹은 a = a; 같은 코드에서 작동할 수 없다.

 

a = b = c의 경우 b = c의 결과가 a에 대입되는데 b = c의 대입이라는 결과는 얻을 수 있지만 void값이 되므로 a = void가 되어 문법에 어긋나기 때문이다. 따라서 위와 같이 함수를 기술해야 한다.

 

반면, a = a; 와 같은 경우 operator=() 함수가 데이터를 복사하기도 전에 원본을 삭제하기 때문에 이상한 값이 출력된다. 따라서 다음과 같이 r-value가 자신이면 대입을 수행하지 않도록 해줘야 한다.

 

if(this == &ref) return;