과제1에서는 C++로 나만의 문자열 클래스를 작성합니다. 이 과제에서 STL 컨테이너, std::string
, cstring
헤더는 사용이 금지됩니다. c-style string과 직접 메모리 관리를 통해서만 구현해야 합니다.
본 문서에서는 MyString
클래스를 구현하면서 고민한 부분들과 해결한 문제들에 대한 내용을 담고 있습니다.
GetCString
메서드의 적절한 반환형 고르기GetCString
메서드는 개체 내부에 저장된 문자열을 C 스타일 문자열(null-terminated string)로 반환합니다. 이는 기존 C의 string 라이브러리와의 호환을 위해서도 필요합니다. 그러나 단순한 char*
로 반환해서는 호출자가 아래와 같이 개체의 일관성을 깨뜨릴 수 있습니다.
따라서 반환형은 char*
보다는 const char*
로 하여 호출자에게 참조만 가능하고 수정은 금지된다는 것을 명확히 보여주는 것이 좋습니다.
덧붙이면, C++ 표준 라이브러리인 std::string
클래스의 c_str
메서드 또한 const char*
를 반환하도록 하고 있습니다.
std::basic_string<CharT,Traits,Allocator>::c_str - cppreference.com
Append(const char* s)
, Interleave(const char* s)
와 같은 메서드는 기존 문자열의 길이를 변경하기 때문에, 내부적으로 더 큰 메모리를 동적 할당한 뒤 기존 데이터를 복사하고, 이전 메모리를 해제하는 작업을 수행합니다.
하지만 매개변수로 empty string이 전달될 경우, 실제로 문자열에 변화가 없으므로 이러한 과정은 불필요한 연산 및 메모리 낭비로 이어집니다.
// BEFORE: empty string에 대해 불필요한 할당 및 복사가 일어남
void MyString::Append(const char* s)
{
// 힙 할당 및 복사, 기존 메모리 해제
}
이를 방지하기 위해, 매개변수로 empty string이 전달될 경우 early return하도록 구현하여, 불필요한 힙 할당 및 복사를 방지했습니다.
// AFTER: empty string이 전달되면 조기 반환
void MyString::Append(const char* s)
{
size_t sLength = strlen(s);
if (sLength == 0)
{
return;
}
// 힙 할당 및 복사, 기존 메모리 해제
}
unsigned
자료형의 underflow 문제IndexOf(const char* s)
메서드에서 s
의 길이가 개체에 저장된 문자열의 길이보다 클 경우, searchCount
의 초기값은 음수값이 되어야 합니다. 그러나 searchCount
의 자료형은 size_t
(unsigned int
)로, underflow가 발생하여 UINT_MAX
에 가까운 매우 큰 수가 저장됩니다.
이러한 상황에서 start < searchCount
조건은 계속 true
가 됩니다. 이는 반복문이 버퍼 범위를 넘어 접근할 수 있는 위험한 연산입니다.