ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [C++] MyString 클래스 실습
    C++ 2023. 4. 13. 22:42

     

    1. 포인터 받을때 nullptr 항상 체크해주기

    2. int 같은거 받을때 0 항상 체크

     

    3. 왜 getLength(const char* in) 은 static인지 이유 알기

     

    int MyString::getLength(const char* in) {
    	if (in == nullptr) return 0; // important
    	int ret = 0;
    	while (*in++ != NULL)  ret++;
    	return ret;
    }

     

    getLength 함수는 해당 클래스 내 멤버변수를 참조하여 사용하진 않지만

    해당 클래스 객체가 사용할 목적으로 정의한 함수이다.

    따라서 static으로 클래스 내부에 넣어두는게 좋다

     

    왜냐하면 만약 static이 아니면 이 함수 하나 호출하기 위해

    불필요한 객체를 생성해야하기 때문이다! (???? 솔까 ㅈㄴ 이상함 이게 이유가 말이 안됨)

     

     

    4. 왜 operator << 는 friend 인지 알아놓기

    5. 왜 append는 참조형 반환이 안되는지 알아놓기

     

    	const MyString& operator+(const MyString& in) { // 이건 reference 붙이면 안됨 이유는?
    		// reference로 넘기면 안되는 이유는
    		// 이 함수가 끝나면 
    		MyString out = *this;
    		out.append(in);
    		return out;
    		// 이 로컬변수 out은 해제되기 때문임!
    
    		// 만약 reference로 넘기고 싶으면
    		// MyString* out = new MyString(*this);
    		// out->append(int);
    		// return *out;
    		// 이렇게 포인터로 외부변수로 해줘야함!
    
    		// 여기서는 그냥 reference로 안넘기는 방법을 제시
    		// const MyString 이렇게 reference로 넘기지 말자
    	}

     

    6. 동적할당이면 무조건 복사생성자 직접 정의 ( 얕은 복사로 안되기 때문 )

    직접 정의해줘 깊은 복사 하게 만들어야함!

    7. 언제 operator를 멤버함수로 해야하는지 외부함수로 해야하는지 알기

    8. const 선언 이해

    ostream& operator<<(ostream& os, const MyString& in) {
    	
    	if (in.m_pStr==nullptr || in.getLength() == 0) return os; // const 선언이면 함수사용은 노빠꾸로 제한함
    	// const는 data type 선언할때, 함수 선언, 참조자 선언할때 쓰임
    	// const 함수는 변하지 않게 한다는것
    	// 그래서 const 함수에서 const 변수를 부르는건 안전하다
    	// 만약 getLength()에 const가 없으면 에러가 난다
    
    	os << in.m_pStr;
    	return os;
    }

     

    9. 대입연산자 자기자신 받을떄 예외처리 ㅈㄴ 중요

    const MyString& MyString::operator=(const MyString& in) {
    	// 같은 놈인지 확인 이거 중요 a=a이면 아래 코드 진행하면 a 데이터만 다 날라가는 ㅈ되는 상황
    	if (this == &in) {
    		return *this;
    	}
    	releaseMemory();
    	m_length = in.getLength(); // length 받고
    	if (m_length == 0) return *this;
    	assignMemory(); // 초기화
    }

     


    [MyString.h]

     

    #ifndef __MYSTRING_H__
    #define __MYSTRING_H__
    
    #include <iostream>
    
    class MyString
    {
    private:
    	char* m_pStr;
    	int m_length;
    
    public:
    	MyString();
    	MyString(const char* in);				
    	MyString(const MyString& in);	// copy constructor (복사생성자)
    	~MyString(); // destructor (소멸자)
    
    	void assignMemory();
    	void releaseMemory();
    
    
    	int getLength() const {return m_length; }
    	static int getLength(const char* in, int max_length=255);
    
    
    	// cout<< overload
    	// 내 객체가 오른쪽에 와야하니까 전역함수로 구현하고 friend 선언
    	// const는 상수로 받는다는 것 왜? 바꿀 이유가 없으니
    	friend std::ostream& operator<<(std::ostream& o, MyString& in);
    	
     
    	// 대입연산자 assignment operator
    	// 항상 왼쪽은 우리꺼 오른쪽은 MyString 타입
    	// 클래스 내 멤버함수로 정의해도 가능
    	const MyString & operator=(const MyString& in);
        
    	const MyString operator+(const MyString& in);
    	void append(const MyString& in);
    };
    
    #endif

     


    [MyString.c]

     

    #include "MyString.h"
    
    
    MyString::MyString()
    {
    	m_pStr = nullptr;
    	m_length = 0;
    }
    
    MyString::MyString(const char* in)
    {
    	m_length = getLength(in);
    	m_pStr = nullptr;
    	if (m_length == 0) return;
    
    	assignMevd5mory();
    
    	for (int i = 0; i < m_length; i++)
    		m_pStr[i] = in[i];
    	m_pStr[m_length] = '\0';
    
    }
    
    MyString::MyString(const MyString& in)
    {
    /*
    	m_pStr = nullptr;
    	m_length = 0;
    	*this = in;
    */ 
    
    	m_pStr = nullptr;
    	m_length = in.getLength();
    	if (m_length == 0) return;
    
    	assignMemory();
    
    	for (int i = 0; i < m_length; i++)
    		m_pStr[i] = in.m_pStr[i];
    	m_pStr[m_length] = '\0';
    
    }
    
    // a = a
    const MyString& MyString::operator=(const MyString& in)
    {
    	if (this == &in) return *this;
    	
    	releaseMemory();
    
    	m_length = in.getLength();
    	if (m_length == 0) return *this;
    
    	m_pStr = new char[m_length + 1];
    	for (int i = 0; i < m_length; i++)
    		m_pStr[i] = in.m_pStr[i];
    	m_pStr[m_length] = '\0';
    	
    	return *this;
    
    }
    
    
    MyString::~MyString()
    {
    	releaseMemory();
    }
    
    void MyString::assignMemory()
    {
    	if (m_length == 0) return;
    	m_pStr = new char[m_length + 1];
    }
    
    void MyString::releaseMemory()
    {
    	if (m_pStr != nullptr)
    		delete[] m_pStr;
    	m_pStr = nullptr;
    	m_length = 0;
    }
    
    int MyString::getLength(const char* in, int max_length)
    {
    	if (in == nullptr) return 0;
    
    	int leng = 0;
    	while (true)
    	{
    		if (in[leng] == '\0') return leng;
    		if (leng >= max_length) return leng;
    		leng++;
    	}
    }
    
    std::ostream& operator<<(std::ostream& o, MyString& in)
    {
    	if (in.m_pStr == nullptr || in.getLength() == 0) return o;
    	o << in.m_pStr;
    	return o;
    }
    
    void MyString::append(const MyString& in)
    {
    	if (in.getLength() == 0) return;
    	MyString temp = *this;
    	
    	if (m_length > 0) releaseMemory();
    	m_length = temp.getLength() + in.getLength();
    	assignMemory();
    
    	for (int i = 0; i < temp.m_length; i++)
    		m_pStr[i] = temp.m_pStr[i];
    	for (int i = 0; i < in.m_length; i++)
    		m_pStr[i + temp.m_length] = in.m_pStr[i];
    	m_pStr[m_length] = '\0';
    }
    
    const MyString MyString::operator+(const MyString& in)
    {
    	MyString out(*this);
    	out.append(in);
    	return out;
    }

    'C++' 카테고리의 다른 글

    [C++] default parameter  (1) 2023.04.19
    [C++] 반환형 참조형 (return값이 참조형일때)  (0) 2023.04.15
    [C++] const  (1) 2023.04.12
    [C++] 접근지정자 (access modifiers)  (3) 2023.04.11
    [C++] friend  (2) 2023.04.11