본문 바로가기
개발/C++ (98,03,11,14,17,20,23)

Modern C++ : string vs std::string vs std::array<char, N> (98, 11, 17)

by snowoods 2025. 8. 11.

Modern C++

문자열 : c-style string vs std::string vs std::array<char, N> vs std::string_view

 

개요

C++에서는 문자열을 다루는 여러 가지 방법을 제공합니다. 이 문서에서는 전통적인 C-style 문자열과 모던 C++에서 권장되는 std::string, 고정 크기 문자열을 위한 std::array<char, N>, 그리고 C++17에 추가된 std::string_view의 특징과 차이점을 비교 설명합니다.

 

C++ 버전별 주요 키워드 도입 시기

  • C++98: std::string (Standard Template Library의 일부로 표준화)
  • C++11: std::array (고정 크기 배열 컨테이너)
  • C++17: std::string_view (문자열에 대한 소유권 없는 뷰)

 

내용 설명

1. C-style 문자열 (char[] 또는 char*)

  • 특징: char 타입의 배열이며, 문자열의 끝을 알리는 null 문자(\0)로 끝납니다. C 언어에서 유래한 가장 기본적인 형태입니다.
  • 장점: C 라이브러리 함수와 직접적인 호환이 가능하고, 오버헤드가 적습니다.
  • 단점: 크기가 고정되어 있거나, 동적 할당 시 수동으로 메모리를 관리해야 합니다. strcpy, strcat 같은 함수 사용 시 버퍼 오버플로우에 취약합니다.

2. std::string

  • 특징: C++ 표준 라이브러리가 제공하는 동적 문자열 클래스입니다. 문자열의 길이를 내부적으로 관리하며, 필요에 따라 자동으로 메모리를 할당하고 해제합니다.
  • 장점: 메모리 관리가 자동화되어 안전하고 편리합니다. append, find, substr 등 풍부한 멤버 함수를 제공하여 문자열 조작이 쉽습니다.
  • 단점: 동적 메모리 할당으로 인해 C-style 문자열보다 약간의 성능 오버헤드가 발생할 수 있습니다.

3. std::array<char, N>

  • 특징: C++11에 도입된 고정 크기 배열 컨테이너입니다. 컴파일 시간에 크기 N이 정해져야 합니다.
  • 장점: 스택에 할당되어 빠르고, STL의 다른 컨테이너처럼 반복자(iterator)를 사용할 수 있어 알고리즘과 함께 사용하기 편리합니다.
  • 단점: 크기를 동적으로 변경할 수 없습니다. null 종결을 보장하지 않으므로 C-style 함수에 전달 시 주의가 필요합니다.

4. std::string_view (C++17)

  • 특징: 문자열 데이터를 소유하지 않고, 기존 문자열의 '뷰(view)' 또는 '참조'만을 가집니다. 읽기 전용입니다.
  • 장점: 문자열을 복사하지 않으므로 함수에 문자열을 전달할 때 발생하는 불필요한 메모리 할당 및 복사 비용이 없습니다. const std::string& 보다 유연하게 다양한 문자열 타입(C-style, std::string 등)을 받을 수 있습니다.
  • 단점: 원본 문자열이 소멸되면 string_view는 유효하지 않은 메모리를 가리키게 되므로(dangling pointer), 생명주기 관리에 주의해야 합니다.

 

예제 코드

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

// C++17의 std::string_view를 사용하는 함수
void print_string_view(std::string_view sv)
{
    // string_view는 복사 없이 문자열을 "바라볼" 뿐입니다.
    std::cout << "View: " << sv << ", Size: " << sv.size() << "\n";
}

int main()
{
    // 1. C-style 문자열
    char my_text1[] = "Jan"; // 컴파일러가 자동으로 null 문자를 추가 (크기 4)
    char my_text2[] = {'J', 'a', 'n', '\0'}; // 명시적 null 종결

    // 2. std::array<char, N>
    // null 문자를 포함할 크기 4로 지정
    auto my_text3 = std::array<char, 4>{"Jan"};

    // 3. std::string
    auto my_text4 = std::string{"Jan"};
    std::cout << "std::string size: " << my_text4.size() << "\n";
    my_text4.append(" Schaffranek");
    std::cout << "Appended string size: " << my_text4.size() << "\n";
    std::cout << "Full string: " << my_text4 << "\n\n";

    // 4. std::string_view 활용
    print_string_view(my_text1);       // C-style string 전달
    print_string_view(my_text4);       // std::string 전달
    print_string_view("Literal");      // 문자열 리터럴 전달

    return 0;
}

 

실행 결과

std::string size: 3
Appended string size: 15
Full string: Jan Schaffranek

View: Jan, Size: 3
View: Jan Schaffranek, Size: 15
View: Literal, Size: 7

 

활용팁

  • std::string: 대부분의 경우에 가장 먼저 고려해야 할 기본 문자열 타입입니다. 안전하고 기능이 풍부하여 생산성이 높습니다.
  • C-style string: C 라이브러리나 오래된 API와 연동해야 할 때 사용합니다. std::string.c_str() 멤버 함수를 통해 쉽게 변환할 수 있습니다.
  • std::array<char, N>: 임베디드 시스템이나 성능이 매우 중요한 환경에서, 컴파일 시간에 크기가 확정된 작은 문자열을 다룰 때 유용합니다.
  • std::string_view: 함수에 읽기 전용 문자열을 전달할 때 사용하면 좋습니다. 불필요한 복사를 방지하여 성능을 향상시킬 수 있습니다. 특히 문자열을 수정할 필요가 없는 함수 매개변수에 const std::string& 대신 사용하는 것을 권장합니다.