본문 바로가기
학교생활!

[230520] 고급C++프로그래밍: 과제3

by Daybreak21 2023. 5. 31.

오류를 찾고 그 오류를 해결하는 과제 

 

메인함수

#include "mystring.h"

void print_safe(mystring& s)
{
	cout << "safe: " << s.get_string() << endl;
}

void print_dangerous(mystring s)
{
	cout << "dangerous: " << s.get_string() << endl;
}

void print()
{
	mystring a("C++ Programming");

	print_safe(a);
	print_dangerous(a);

}

void foo()
{
	mystring a("Sungshin University");
	mystring b = a;

	print_safe(a);
	print_safe(b);
}

int main()
{
	print();
	foo();

	return 0;
}

수정 전 mystring.h

#pragma once
#include <iostream>
using namespace std;

class mystring {
private:
	int len;
	char* str;
public:
	mystring() : str(NULL), len(0) { }
	mystring(const char* s) : str(new char[len + 1]), len(length(s)) { copy(s); }
	~mystring()
	{
		if (str != NULL) {
			delete[]str;
			str = NULL;
			len = 0;
		}
	}

	char* get_string() const
	{
		return str;
	}

	void set_string(char* s)
	{
		len = length(s);
		if (str != NULL) delete[]str;
		str = new char[len + 1];
		copy(s);
	}

private:
	int length(const char* s)
	{
		int len = 0;

		while (*s++ != '\0') len++;
		return len;
	}

	void copy(const char* s)
	{
		for (int i = 0; i <= len; i++) str[i] = s[i];
	}
};

이사진과 같이 mystring이 디폴트복사생성자를 사용하여 멤버 대 멤버를 단순복사하면서 포인터주소도 복사하여 가르키고 있다. 

이로인해 객체 소멸과정에서 b의 소멸자가 호출되어 str의 문자열이 소멸되면, a객체가 소멸될때 이미 지워진 문자열을 delete할려고 시도하기 때문에 오류가 발생한다. 

 

 

추가한 부분: 복사생성자 정의 

    mystring(const mystring& a) {
        len = length(a.get_string());
        str = new char[len + 1];
        copy(a.get_string());
    }
    
    char* get_string() const
	{
		return str;
	}

 

  • 멤버변수 len의 멤버 대 멤버 복사
  • 메모리 공간 할당 후 문자열 복사, 할당된 메모리 주소 값을 멤버 str에 저장

위 코드를 추가하면서 멤버변수가 참조하는 문자열을 복사하여 두 객체가 별개의 문자열을 소유하도록 하였다. 

mystring의 멤버변수는 private로 선언되어있기때문에 get_string함수를 이용하여 len과 str을 설정해주었다. 

 

복사생성자를 정의할 때의 매개변수를 const로 받고 있기때문에 복사생성자 안에서 a의 값을 직접적으로 바꿀 수 없기때문에  get_string에 const를 붙여 멤버를 바꾸지 않는 다는 것을 확실시 해주었다. 

 

※매개변수가  const인 객체인 함수들은 인수로 받은 해당 객체의 멤버 함수를 사용할 때 꼭 뒤에 const가 붙은 함수만 사용할 수 있게 된다.