C++_OOP5

gimmicks_u·2022년 4월 4일
0

C++

목록 보기
5/5
post-thumbnail

클래스의 동적 메모리 할당

대입 연산자 오버로딩

기호가 같은 연산자를 여러 가지 기능을 가질 수 있도록 정의할 수 있다. 이를 연산자 오버로딩이라고 한다.

#include <iostream>
using namespace std;
class String
{
public:
    String(char ch, int nSize);
    ~String();
    void operator=(const String& s);
    void SetData();

private:
    int nLength;
    char *pBuffer;
};

String::String(char ch, int nSize)
{
    nLength = nSize;
    pBuffer = new char[nLength + 1];
    memset(pBuffer, ch, nLength);
    pBuffer[nLength] = '\0';
    cout << "pBuffer : " << pBuffer << endl;
    cout << "nLength : " << nLength << endl;
}

String::~String()
{
    delete[] pBuffer;
}

void String::operator=(const String& s) // & : CallbyReference하겠다!
{
    delete pBuffer;
    nLength = s.nLength;
    pBuffer = new char[nLength + 1];
    strcpy(pBuffer, s.pBuffer);
}

void String::SetData()
{
    cout << "pBuffer : " << this->pBuffer << endl;
    cout << "nLength : " << this->nLength << endl;
}

int main()
{
    String str1('A', 5);
    String str2('B', 5);
    str1 = str2;
}
pBuffer : AAAAA
nLength : 5
pBuffer : BBBBB
nLength : 5

str1 = str2;
str2.operator=(str1);

두 문장 모두 같은 것이다. 위처럼 본다면 더 직관적으로 이해할 수 있다.

객체의 자기 자신 대입 시에 대한 처리

str1 = str1;

자기 자신을 대입시 먼저 str1이 가르키는 메모리가 delete될것이고, 새로운 메모리 공간을 힙영역에 nLength길이만큼 할당한다. 문제는 strcpy()시에 s.pBuffer값을 가지고 올 수 없으므로 결국 복사는 실패하게 된다.

void String::operator=(const String& s)
{
    if(&s == this)
        return;
    delete pBuffer;
    nLength = s.nLength;
    pBuffer = new char[nLength + 1];
    strcpy(pBuffer, s.pBuffer);
}

operator=()멤버함수에서 전달인자로 넘겨받은 클래스 객체현재 멤버함수의 소속 클래스가 같은지 검사해서 코드는 실행되지 않도록 return 처리하면 문제를 해결할 수 있다.

복사 생성자

String str1('A',3);
String str2 = str1; // 복사 생성자1
String str2(str1); // 복사 생성자2

객체 생성 시 초기화를 하되, 생성되는 객체를 다른 객체로 초기화 할 때 호출되는 생성자.

#include <iostream>
using namespace std;
class String
{
public:
    String(char ch, int nSize);
    ~String();
    String(const String& s);
    void operator=(const String& s);
    void SetData();

private:
    int nLength;
    char *pBuffer;
};

String::String(char ch, int nSize)
{
    nLength = nSize;
    pBuffer = new char[nLength + 1];
    memset(pBuffer, ch, nLength);
    pBuffer[nLength] = '\0';
    // cout << "pBuffer : " << pBuffer << endl;
    // cout << "nLength : " << nLength << endl;
}

String::~String()
{
    delete[] pBuffer;
}

String::String(const String& s)
{
    this->nLength = s.nLength;
    this->pBuffer = new char[this->nLength + 1];
    strcpy(this->pBuffer, s.pBuffer);
}

void String::operator=(const String& s)
{
    if(&s == this)
        return;
    delete pBuffer;
    this->nLength = s.nLength;
    this->pBuffer = new char[this->nLength + 1];
    strcpy(this->pBuffer, s.pBuffer);
}

void String::SetData()
{
    cout << "pBuffer : " << this->pBuffer << endl;
    cout << "nLength : " << this->nLength << endl;
}

int main()
{
    String str1('A', 5);
    String str2(str1);
    // String str2 = str1;  윗문장과 같음
    cout << "대입 후 str2" << endl;
    str2.SetData();
}
대입 후 str2
pBuffer : AAAAA
nLength : 5

operator에서는 pBufferdelete를 해주었지만, 복사생성자에서는 delete를 하지 않는다. 그 이유는 operator에서는 기존에 있던 데이터를 없애고 값을 받아야 했지만, 복사 생성자에서는 객체가 처음 생성되는 시점이기 때문에 delete할 필요가 없기 때문이다.

profile
Done is better than perfect

0개의 댓글

관련 채용 정보