안녕하세요. 이번 글에서는 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에 대해 간단히 알아보았습니다.