c++ 복사생성자 (연산자 오버로딩)

‍정진철·2022년 9월 10일
0

C++

목록 보기
11/18

연산자 오버로딩

  • 등호 연산자는 '얕은복사'가 일어나게 됨으로써 원래 객체가 지정하고 있던 값만 둥둥떠다니고 포인터 해제시 해제가 안되는 포인터 주소가 발생됨.


  • rhs에 '&'를 붙이는 이유는 & 없이 String s2(s1) ; 와 같이 하면 rhs 에 s1이 복사가 되므로 복사생성자가 호출되어 복사생성자 코드를 새롭게 또 다시 만들게 된다.
  • 하지만 그렇게 하지않고 '&'를 사용한다면 복사생성자의 기능없이 call by reference처럼 s1객체를 단순 '가르키고'있는 상태이므로 객체 복사가 이루어지지 않음.
  • 반환타입에 '&'를 붙이는 이유는 s3.operator=(s1); 과 같은 코드 실행시 s3에 operator의 반환값이 복사가 된다면 임시객체가 생성되는 순간에 또 복사가 이루어짐.
  • 따라서 반환타입(operator)에 레퍼런스를 붙여줌으로써 추가되는 복사행위를 막을 수 있음.

  • s3 = s1; 이나 s3.operator=(s1); 은 동일한 의미.

Code

#include <iostream>
using namespace std;

class String
{
public:
    String()
    {
        cout << "String() 생성자 호출" << endl;
        strData = NULL;
        len = 0;
    }
    String(const char *str)
    {
        cout << "String(const char *) 생성자 호출" << endl;
        len = strlen(str);
        strData = new char[len + 1];
        cout << "StrData 할당: " << (void *)strData << endl;
        strcpy(strData, str);
    }

    //매게변수로 String 클래스 타입을 받는것.
    String(const String &ref)
    {
        cout << "String(String &ref) 생성자 호출" << endl;
        strData = new char[ref.len + 1];
        cout << "strData 할당: " << (void *)strData << endl;
        strcpy(strData, ref.strData);
        len = ref.len;
    }

    ~String()
    {
        cout << "~String() 소멸자 호출" << endl;
        delete[] strData;
        cout << "strData 해제됨: " << (void *)strData << endl;
        strData = NULL;
    }

    String &operator=(const String &rhs)
    {
        delete[] strData;
        strData = new char[rhs.len + 1];
        cout << "strData 할당: " << (void *)strData << endl;
        strcpy(strData, rhs.strData);
        len = rhs.len;

        return *this;
    }
    char *GetstrData() const
    {
        return strData;
    }

    int Getlen() const
    {
        return len;
    }

private:
    char *strData;
    int len;
};

int main()
{
    String s1("안녕");
    String s2(s1); //복사생성자
    String s3;
    s3.operator=(s1);

    cout << s1.GetstrData() << endl;
    cout << s2.GetstrData() << endl;
    cout << s3.GetstrData() << endl;
}

  • delete[] -> 이전 객체에 대한 주소값이 할당된 경우가 있으므로 사전에 제거 후 새로운 객체 생성.
    이전 객체에 아무런 값이 없으면 delete 하더라도 아무런 반응 없음.

Ex)

  • 반환값으로 rhs 반환은 const String타입이므로 String으로 반환불가.
  • 따라서 this를 사용함으로써 함수가 실행될 당시의 객체의 주소값 ('*'을 붙여주면 해당 value 반환)

참조 : https://www.youtube.com/watch?v=hsnOQiotbKs

profile
WILL is ALL

0개의 댓글