C++ 프로그래밍/자료구조와 알고리즘

[자료구조와 알고리즘] String Class 생성자와 제거자

SW Developer 2024. 2. 26. 00:26

String Class 생성자와 제거자

:String Class의 생성자와 제거자 코드를 작성해보자

<<

 

 

1. Storage Class의 기억부류

 

① 자동변수 (Automatic Variables)

- 정의와 동시에 생성되고, 블럭({ })이 끝날 때 제거되는 변수

- 스택(Stack)에서 생성된다 (reentrant 가능)

 

② 정적변수 (Static Variables)

- 프로그램 시작과 동시에 생성되고, 프로그램이 끝날 때 제거되는 변수

- Data Segment에서 할당된다

 

③ 동적변수 (Dynamic Variables)

- new로 생성되고, delete로 제거되는 변수

- Heap Memory에서 생성된다

 

Storage 예시

#include <iostream>
using namespace std;

int global; //Static, 정적변수

int main(){
  static ins staticvar = 10; //Static, 정적변수
  
  char* dynamic = new char[10];//Dynamic, 동적변수
  //do something
  delete[] dynamic;
  
  int local1 = 0; //Automatic, 자동변수
  if(local1 == 0){
    int local2;  //Automatic, 자동변수
    local2 = 0;
  }
  //do something
}

 

 

2. Constructor (생성자)

 

생성자란?

- 객체가 새로 만들어질 때, 자동으로 호출되는 함수를 말한다

- 객체의 초기화를 담당한다

- Class의 이름과 동일하며, Overload가 가능하다

- 리턴값이 별도로 존재하지 않는다

- Default Constructor (인자 없는 생성자)가 있으며, 이는 배열 생성 시 반드시 필요하다

 

상속과 생성자

- Base Class (기초클래스)의 생성자를 호출하는 방법은 아래와 같다

DerivedClass(Args) : BaseClass(Args)
{
	//body
}

 

 

3. Destructor (제거자)

 

제거자란?

- 객체가 제거될 때 자동으로 호출되는 함수다

- 주로 객체가 할당한 리소스를 해제하는 역할을 수행한다

- 클래스의 이름 앞에 ~ (틸태)를 붙인다.

- 인자 및 리턴값이 별도로 존재하지 않는다

- 상속이 사용되는 클래스의 경우 virtual을 붙여야 한다

 

 

4. Copy Initializer Constructor (복제 생성자)

 

복제 생성자란?

- 같은 타입의 객체로부터 생성된(복제된) 새로운 객체를 의미한다

X::X(const X&)

 

※ 복제 생성자가 작동하는 경우

- 다른 객체로부터 만들어질 때

- 객체를 함수의 인자로 넘길 때

- 함수에서 객체를 리턴할 때

 

* 복제 생성자 생성 시 주의사항

"복제생성자가 작동하는 경우"와 "연산자 = 를 통해 생성자를 할당하는 경우"를 명확히 구분해야 한다. 

String some_function(String str)
{
    String strReturn;
    //do something
    return strReturn;
}

int main(){
    String str1 = "Test String";

    //복제 생성자가 작동하는 경우
    String str2 = str1; 
    str2 = some_function(str1); //strReturn 호출

    //연산자 = 를 통해 생성자를 할당하는 경우
    String str3;
    str3 = str1;
}

 

 

위 1 ~ 4 개념을 활용하여, 아래와 같이 String 클래스의 생성자, 제거자에 대한 코드들을 추가한다.

 

① String Class에 생성자, 제거자의 원형 제공

class String
{
    protected:
    	int len;
        char* m_pBuffer; //string 버퍼
        void _Init();
        void _Clear();
        void _Copy(const char* lpsz);
    public:
        //constructors,destructor
        String(); //default constructor
        String(const String&); //copy constructor
        String(char*);
        String(const char*);
        String(char);
        String(long);
        String(int);
        String(double);
        ~String();

        //operators: 추후 추가 예정
        //other member functions: 추후 추가 예정
};

 

 

② String 생성자, 제거자에 대한 정의 추가

//(추가) 생성자,파괴자
String::String() {
	_Init();
}
String::String(const String& stringSrc) {
	_Init();
	len = strlen(stringSrc.m_pBuffer);
	_Copy(stringSrc.m_pBuffer);
}
String::String(const char* lpsz) {
	_Init();
	len = strlen(lpsz) + 1;
	_Copy(lpsz);
}
String::String(char* lpsz) {
	_Init();
	len = strlen(lpsz) + 1;
	_Copy(lpsz);
}
String::String(char ch) {
	char str[2];
	str[0] = ch;
	str[1] = '\0';

	_Init();
	len = 2;
	_Copy(str);
}
String::String(long l) {
	_Init();
	
	char num_char[10 + sizeof(char)];
	sprintf(num_char, "%d", l);
	len = strlen(num_char);
	_Copy(num_char);
}
String::String(int i) {
	_Init();

	char num_char[10 + sizeof(char)];
	sprintf(num_char, "%d", i);
	len = strlen(num_char);
	_Copy(num_char);
}
String::String(double d) {
	_Init();
	
	char num_char[10 + sizeof(char)];
	sprintf(num_char, "%d", (int)d);
	len = strlen(num_char);
	_Copy(num_char);
}
String::~String() {
	_Clear();
}


//(기존) void 함수
void String::_Init() {
	len = 0;
	m_pBuffer = 0;
}
void String::_Clear() {
	if (m_pBuffer)//m_pBuffer != 0 일 때
		delete[] m_pBuffer;
	_Init();
}
void String::_Copy(const char* lpsz) {
	if (lpsz != 0) {
		m_pBuffer = new char[strlen(lpsz) + 1];//null이 저장되는 공간 +1 추가
		if (m_pBuffer)
			strcpy(m_pBuffer, lpsz);
	}
}

 

 

③ main코드에 String 클래스 Object 초기화하기

int main() {
	//Constructor Test
	String str1;		     //default Constructor
	String str2("I can do"); //Constructor
	String str3(" it!!");    //Constructor
	String str4('A');        //Constructor
	String str5 = str4;	     //Copy Constructor
	String str6(156);		 //Constructor
	String str7(1.1);		 //Constructor
    
    return 0;
}

 

 


※ 출력함수 printf, sprintf, snprintf

 

printf ("문자열과 서식", 변수 1, 변수 2)

: 첫 번째 인자인 문자열을 화면에 출력해주는 함수이다.

int printf(const char* format,변수1,변수2,...);

 

코드 예시

#include <stdio.h>

int main(){
   char cA = 'A';
   printf("The cA is %c and %d in decimal.\n",cA,cA);
}

 

 

printf()의 서식문자 및 특수 제어문자

서식문자 특수 제어 문자
구분 기호 출력 형태 문자 기능
정수형 %d  10진수 정수 \n 줄바꿈
%x 16진수 정수 \t 수평 탭(tab)
%c 문자 \a beep 음 발생
실수형 %f 10진수 실수 (float형) \\ 역슬래시 문자(\) 표시
%e 10진수 실수 (지수형 표기) \" 따옴표 문자 표시
%lf 10진수 실수 (double형)    
문자열 %s 문자열 출력    

 

 

sprintf (버퍼 변수, 포멧1, 포멧 2)

: printf()와 유사하면서도 다른 점은, 문자열을 출력하는 printf()와 달리 sprintf()는 버퍼로 사용될 변수가 출력된다는 점이다. 즉, char* 로 선언된 변수 안에 입력된 내용이 문자열로 담기게 된다.

int sprintf(char* buffer, const char *format, ...);

 

 코드 예시

int main() {
	char buf[256];
	int len;

	len = sprintf(buf, "I love you %d\n",3000);
	printf("%s\n", buf); 
}

 

 

③ snprintf (버퍼 변수, SIZE, 포멧1, 포멧 2)

: snprintf()sprintf()에서 2번째 파라미터에 SIZE가 추가된 함수이다. 이 함수는 문자열의 길이를 지정하여, 버퍼 오버플로우를 막을 때 유용하다

int sprintf(char* buffer, int buf_size, const char *format, ...);

 

 

 

 

 

 

※ 해당 게시글은 개인 학습의 목적으로, 아래 강의를 수강한 후 정리한 학습노트입니다.

https://inf.run/LNCU