[C++] std::string_view : 복사 없이 문자열 읽기

[C++] std::string_view : 복사 없이 문자열 읽기

안녕하세요. 이번 글에서는 C++17에서 추가된 std::string_view에 대해 알아보겠습니다.

문자열을 함수 인자로 넘길 때 const std::string&를 쓰면 문자열 리터럴이 들어올 때마다 임시 std::string이 만들어지고, const char*를 쓰면 길이를 매번 다시 계산해야 합니다. string_view는 문자열의 시작 주소와 길이만 가진 읽기 전용 뷰로, 복사 없이 다양한 문자열을 같은 방식으로 받을 수 있습니다.

기본 사용법

헤더는 <string_view>이며 C++17 이상(-std=c++17)이 필요합니다. string, 문자열 리터럴, char 배열을 모두 복사 없이 받을 수 있습니다.

#include <iostream>
#include <string>
#include <string_view>
using namespace std;

// before : 리터럴을 넘기면 임시 std::string이 생성됨
void PrintOld(const string& s) { cout << s << "\n"; }

// after : 복사 없이 모두 받음
void Print(string_view sv)
{
    cout << sv << " (" << sv.size() << ")\n";
}

int main()
{
    string str = "Hello, string";
    const char* cstr = "Hello, C string";

    Print(str);                  // std::string
    Print(cstr);                 // const char*
    Print("Hello, literal");     // 리터럴
}

string_view는 값 복사 비용이 포인터와 길이 정도이므로 const 참조가 아니라 값으로 전달하는 것이 일반적입니다.

주요 멤버 함수

함수설명
size(), length()문자 개수
empty()비어 있는지 확인
data()시작 주소 (널 종료가 보장되지 않음)
substr(pos, len)부분 뷰 반환 (복사 없음)
remove_prefix(n) / remove_suffix(n)앞 / 뒤에서 n문자를 뷰에서 제외
find(), compare(), starts_with(), ends_with()탐색·비교 (starts_with, ends_with는 C++20)

substr은 std::string과 달리 새 문자열을 만들지 않고 같은 메모리의 다른 구간을 가리키는 뷰를 돌려줍니다.

string_view sv = "key=value";
auto pos = sv.find('=');

string_view key = sv.substr(0, pos);    // "key"
string_view val = sv.substr(pos + 1);   // "value"
cout << key << " " << val << "\n";

주의할 점 : 소유하지 않는다

string_view는 문자열을 소유하지 않고 가리키기만 하므로, 가리키는 원본이 사라지면 dangling 상태가 됩니다. 가장 흔한 실수는 임시 객체를 가리키는 경우입니다.

string GetName() { return "temporary name"; }

string_view bad = GetName();   // 임시 string이 문장 끝에서 소멸 → bad는 dangling
// cout << bad;                // 정의되지 않은 동작

string name = GetName();
string_view ok = name;         // name이 살아 있는 동안만 유효
  • 함수의 반환 타입이나 클래스 멤버로 string_view를 두면, 원본의 수명을 따로 관리해야 합니다.
  • data()는 널 종료를 보장하지 않으므로 C 함수(printf, fopen 등)에 그대로 넘기면 안 됩니다.
  • string_view에서 std::string이 필요하면 string(sv)처럼 명시적으로 변환합니다. 암시적 변환은 되지 않습니다.
  • string_view끼리는 + 연산으로 이어 붙일 수 없습니다.

정리

std::string_view는 문자열을 복사하지 않고 읽기 전용으로 참조하는 가벼운 타입입니다. 문자열을 읽기만 하는 함수의 매개변수에 쓰면 string, const char*, 리터럴을 모두 받을 수 있고 불필요한 임시 객체도 줄어듭니다. 대신 원본의 수명을 책임지지 않으므로 임시 객체를 가리키거나 멤버로 오래 보관하지 않도록 주의해야 합니다.

이상으로 std::string_view에 대해 간단히 알아보았습니다.

참고