[C++] 대입 연산자 오버로딩

DONE_WALLE
Research Team — DAWN
4 min readMar 17, 2022

--

대입 연산자란 변수에 값을 대입할 때 사용하는 이항 연산자입니다. ( = )

오버로딩이란 함수의 이름이 같고, 시그니쳐의 타입 혹은 개수에 따라 함수가 구분되는 것을 말합니다. 반환형은 중요하지 않습니다.

연산자 오버로딩이란 클래스의 성격에 따라 기능을 재정의 하는 것 입니다. 오버로딩한 함수는 operator<연산자>형태의 이름을 가지고 있습니다. 이항 연산자의 경우 좌측의 피연산자는 호출할 객채가되며 우측의 피연산자는 인수가 됩니다.

연산자 오버로딩 방법은 크게 멤버함수에 의한 오버로딩일반 함수에 의한 오버로딩으로 2가지가 있습니다.

대입 연산자의 오버로딩 특징

  • 개발자가 정의하지 않아도 모든 클래스는 디폴트 대입 연산자가 있습니다. ( 생략됨 )
  • 디폴트 대입 연산자는 얕은 복사를 합니다. (얕은복사:주소만 복사, 깊은 복사: 주소를 복사하여 넘겨주는 게 아니라 새로운 메모리를 할당받아 내용물만 복사)
  • 연산자 내에서 동적 할당을 하거나 깊은 복사가 필요하면 직접 정의를 해야 합니다.
  • 객체 두 개가 이미 생성 및 초기화가 진행된 상태에서 대입을 할 때 호출 됩니다.
  • 객체 자체와 직접적인 연관이 있기때문에 클래스의 멤버 함수로만 정의 할 수 있으며 전역 함수로는 정의할 수 없습니다.
  • 정적함수로도 만들 수 없고 반드시 일반 멤버 함수로 만들어야합니다.

대입연산자는 A& A::operator=(const A& obj) 와 같은 원형을 가지고 있고 오버로딩 대입 연산자는 하나의 객체를 기존의 다른 객체에 대입 할 때 호출됩니다. 생성하면서 대입하는 과정에서는 항상 복사 생성자가 호출됩니다. 복사 생성자와 대입 연산자를 통해 문자열 주소를 맴버별 복사하게 되는데, 동일한 주소의 메모리를 중복으로 해제하는 경우가 되므로 문제가 생깁니다. 이러한 복사 생성자가 아닌 대입 연산자로 인한 문제를 해결하기 위해서는 아래와 같은 방법이 있습니다.

대입에서 발생하는 문제의 해결책 몇 가지

  1. 깊은 복사를 하는 대입 연산자 정의를 사용자가 직접 정의합니다.
  2. 객체를 자기자신에게 대입하지 못하게 합니다.

is(this == &obj) return *this;

3. 이전에 대입된 데이터를 참고할 수 있으므로 delete를 사용하여 메모리를 해제해줍니다.

delete [] str;

len = obj.len;

str = new char[len+1]; // 새 문자열을 위한 메모리 할당

str::strcpy(str, obj.str); // 새로운 공간에 문자열 복사

4. 호출한 객체에 대한 참조를 반환합니다.

return * this;

5. 복사 생성자 앞에 explicit을 붙입니다.

아래의 코드는 press_material 클래스를 깊은 복사를 한 것입니다. 새로운 공간을 할당해서 복사 대상이 되는 객체가 가리키는 내용물들을 일일이 복사했습니다. Copy_Data의 객체가 press_material의 객체로부터 멤버 값들을 복사 받을 때 새로운 공간을 할당해서 내용물만 옮긴 거라 두 객체의 데이터는 다른 공간을 가리키고 있습니다.

return *this; 와 같이 참조형으로 리턴한 이유는 대입연산은 A1 = A2 = A3 와 같은 형태로도 쓰기 때문에 참조형으로 리턴을 해줘야 합니다.

테스트를 위해 간단히 두 객체만 출력해보니 Org와 Copy가 같은 값을 출력하는 것을 확인 할 수 있었습니다.

--

--