[모던 C++ #5] C-Style 문자열을 넘어: std::string과 std::string_view로!

과거 C++98/03 시절에는 문자열 처리를 위해 C-Style 문자열(char*)을 직접 다루는 경우가 많았습니다. 그러나 C-Style 문자열은 널 종단 문자('\0')를 통해 문자열의 끝을 인식하고, 이를 다루는 과정에서 범위 초과, 메모리 누수, 버퍼 오버플로우 같은 위험이 상존했습니다. 또한 문자열 조작을 위해 std::strlen, std::strcpy 등 C 표준 라이브러리 함수를 반복적으로 사용하는 것은 번거롭고 오류를 내기 쉬운 방식이었습니다.

모던 C++에서는 이러한 문제를 해결하기 위해 std::string과 C++17 이후의 std::string_view를 활용할 수 있습니다. 이로써 문자열 처리가 안전하고 직관적이며, 성능까지 고려한 형태로 진화했습니다.

관련 참고 자료:

과거: C-Style 문자열의 문제점

C-Style 문자열은 문자열 리터럴이나 동적 할당된 char 배열로 표현되며, 사용자가 직접 널 종단을 신경 써야 합니다.

#include <cstdio>
#include <cstring>

int main() {
    const char* cstr = "Hello";
    char buffer[10];
    std::strcpy(buffer, cstr); // buffer에 Hello 복사
    std::printf("%s\n", buffer);

    // 버퍼 크기 미확인 복사
    // char small[3];
    // std::strcpy(small, "Hello"); // 오버플로우 발생 위험!
    return 0;
}

위 예제에서 small에 "Hello"를 복사하면 버퍼 오버플로우가 발생할 수 있습니다. 이처럼 C-Style 문자열 처리는 관리가 까다롭고, 실수하기 쉽습니다.

현재: std::string과 std::string_view

std::string: 안전하고 편리한 문자열 관리

std::string은 동적 메모리 관리와 널 종단 처리를 내부적으로 처리하며, 다양한 멤버 함수를 통해 문자열 조작을 간편하게 할 수 있습니다. 또한 표준 컨테이너와 유사한 인터페이스를 제공하므로, 다른 STL 알고리즘과 자연스럽게 연계할 수 있습니다.

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello";
    str += " World"; // 문자열 붙이기
    std::cout << str << "\n"; // Hello World 출력

    // 부분 문자열, 검색, 길이 등 다양한 기능 제공
    std::cout << "Length: " << str.size() << "\n"; 
    std::cout << "Substring: " << str.substr(0,5) << "\n"; // Hello
    return 0;
}

std::string을 사용하면 범위 초과 접근이나 널 종단 관리 같은 저수준 세부사항에 신경 쓸 필요가 적어집니다.

std::string_view: 복사 없는 문자열 뷰

C++17에서 도입된 std::string_view는 기존 문자열(std::string, C-Style 문자열)을 "비소유(non-owning) 뷰"로 참조할 수 있게 해줍니다. 이는 문자열을 복사하지 않고 부분 문자열을 처리하거나, 함수 인자로 문자열을 전달할 때 가벼운 참조만 하도록 합니다.

#include <iostream>
#include <string>
#include <string_view>

void print_sv(std::string_view sv) {
    std::cout << sv << "\n";
}

int main() {
    std::string str = "Hello World";
    print_sv(str); // 복사 없이 문자열 뷰로 전달
    print_sv(str.substr(6)); // "World"만 뷰로 참조

    const char* cstr = "C-Style";
    print_sv(cstr); // C-Style 문자열도 그대로 참조 가능
    return 0;
}

std::string_view를 사용하면, 함수 인자로 문자열을 넘길 때 추가 복사 비용을 절감할 수 있으며, 문자열 조작도 보다 효율적으로 할 수 있습니다.

왜 이런 변화가 필요한가?

  1. 메모리 안전성
    std::string은 문자열 관리에서 널 종단과 할당 해제 같은 작업을 자동화하므로, 메모리 안전성을 크게 강화합니다.
  2. 편의성과 가독성 향상
    std::string과 std::string_view는 다양한 멤버 함수를 통해 문자열 연산을 직관적으로 수행할 수 있어, 코드 가독성과 유지보수성을 높입니다.
  3. 성능 최적화
    std::string_view를 통해 불필요한 문자열 복사를 줄일 수 있으며, 부분 문자열 처리 시에도 추가적인 메모리 할당이 없어 성능 이점을 누릴 수 있습니다.

 

반응형