absl::string_view — non-owning 문자열 참조
#한 줄 요약
absl::string_view는 포인터 + 길이만 보유하는 non-owning 참조 타입이다. const std::string& 매개변수가 강제하는 임시 복사와 alloc 경로를 제거하기 위해 도입됐고, 함수 시그니처의 input 문자열 표현을 단일화하는 기반 타입이다.
#왜 string_view가 필요한가
전통적 시그니처는 const std::string&이다. 그러나 이 타입은 호출 측에 부담을 안긴다.
// 회피bool StartsWithBoo(const std::string& s);
// 호출 측에서 std::string 객체가 강제됨StartsWithBoo("boom"); // 임시 string 객체 alloc + 복사char c[] = "boom";StartsWithBoo(c); // 임시 string 객체 alloc + 복사
absl::string_view sv = "boom";StartsWithBoo(std::string(sv)); // 호출 측이 변환 비용을 지불std::string&를 받는다는 사실만으로 모든 호출 경로에 alloc이 끼어든다. 짧은 문자열도 SSO(short string optimization) 임계치를 넘으면 힙으로 간다. 빈번히 호출되는 비교 함수에서 이는 무시할 수 없는 비용이다.
string_view는 이를 해소한다.
// Goodbool StartsWithBoo(absl::string_view s);
StartsWithBoo("boom"); // alloc 없음StartsWithBoo(std::string("boom")); // alloc 없음 (std::string → view)StartsWithBoo(absl::string_view("boom")); // alloc 없음호출 측이 어떤 형태로 문자열을 들고 있든 view 한 번에 수렴한다.
#API와 사용법
absl::string_view의 인터페이스는 std::string_view(C++17)와 동일하다. 핵심만 보면 다음과 같다.
namespace absl {class string_view { public: // 생성 constexpr string_view() noexcept; // 빈 view constexpr string_view(const char* data, size_t len); // 명시 길이 string_view(const char* str); // strlen string_view(const std::string& s) noexcept; // 변환
// 접근 constexpr const char* data() const noexcept; constexpr size_t size() const noexcept; constexpr bool empty() const noexcept; constexpr char operator[](size_t i) const;
// 잘라내기 (새 view 생성, alloc 없음) constexpr string_view substr(size_t pos, size_t n = npos) const; constexpr void remove_prefix(size_t n); constexpr void remove_suffix(size_t n);
// 검색 size_t find(string_view s, size_t pos = 0) const noexcept; size_t rfind(string_view s, size_t pos = npos) const noexcept;
// 변환 explicit operator std::string() const; // alloc 발생};}핵심은 substr, remove_prefix, remove_suffix가 alloc 없이 view를 갱신한다는 점이다. std::string의 동일 연산은 새 문자열을 만든다.
// std::string — 매 substr마다 allocstd::string log = "2026-05-23T19:00:00 INFO ...";std::string date = log.substr(0, 10); // allocstd::string level = log.substr(20, 4); // alloc
// absl::string_view — alloc 0absl::string_view log = "2026-05-23T19:00:00 INFO ...";absl::string_view date = log.substr(0, 10); // 포인터+길이만 갱신absl::string_view level = log.substr(20, 4);#내부 구현
absl::string_view는 두 필드만 갖는다.
// absl/strings/string_view.h (요약)class string_view { const char* ptr_; size_t length_; public: // ...};sizeof(absl::string_view) == sizeof(void*) + sizeof(size_t)로, 64-bit에서 16바이트다. 레지스터 한 쌍에 들어가는 크기다. 전달은 값으로 한다.
// 권장 — 값으로 받는다void Parse(absl::string_view input);
// 회피 — 참조로 받을 이유가 없다 (이미 충분히 작다)void Parse(const absl::string_view& input);ptr_는 null이 아니더라도 null-terminated 보장이 없다. 이 점이 C API와의 마찰을 만든다.
#std::string_view와의 관계
C++17부터 std::string_view가 표준에 들어왔다. Abseil은 ABSL_USES_STD_STRING_VIEW 플래그에 따라 alias로 동작한다.
// absl/strings/string_view.h (요약)#ifdef ABSL_USES_STD_STRING_VIEWnamespace absl {using string_view = std::string_view;}#elsenamespace absl {class string_view { /* ... */ };}#endifC++17 이상 빌드에서는 absl::string_view가 std::string_view의 별칭이다. 둘 다 ABI 호환이고, 인터페이스도 동일하다. 새 코드라면 std::string_view로 적어도 무방하나, Google 사내 스타일은 Abseil 일관성을 위해 absl::string_view를 선호한다.
#코드 리뷰 포인트
리뷰에서 가장 자주 보이는 권장 변환은 다음 세 가지다.
1. 함수 매개변수의 const std::string& → absl::string_view
// 회피absl::Status SaveUser(const std::string& name);
// Goodabsl::Status SaveUser(absl::string_view name);저장 시점에 std::string이 필요하면 함수 안에서 std::string(name)으로 변환하면 된다. 호출 측에 비용을 떠넘기지 않는다.
2. 임시 substring 추출
// 회피 (alloc 발생)if (path.substr(0, 5) == "/api/") { ... }
// Good (alloc 없음)absl::string_view path_view = path;if (path_view.substr(0, 5) == "/api/") { ... }
// 더 Goodif (absl::StartsWith(path, "/api/")) { ... }3. 검색·비교 헬퍼는 view를 받는다
bool absl::StartsWith(absl::string_view s, absl::string_view prefix);bool absl::EndsWith(absl::string_view s, absl::string_view suffix);bool absl::StrContains(absl::string_view haystack, absl::string_view needle);이 함수들이 string_view를 받기 때문에 const std::string&로 받는 사용자 정의 헬퍼는 일관성을 깨뜨린다.
#안티패턴
값 보관
string_view는 데이터의 소유권이 없다. 멤버 변수로 보관하면 dangling 위험이 생긴다.
소유와 view의 관계, 그리고 위험한 dangling 케이스를 그림으로 보면 다음과 같다.
// 회피class UserCache { absl::string_view user_name_; // dangling 위험 public: void SetName(absl::string_view name) { user_name_ = name; }};
// Good — 보관할 거면 std::string으로class UserCache { std::string user_name_; public: void SetName(absl::string_view name) { user_name_ = std::string(name); }};상세는 다음 글 Part 4-02 — string_view 함정에서 다룬다.
c_str() 기대
string_view에는 c_str()이 없다. null-terminated가 아니기 때문이다. C API에 넘기려면 std::string으로 변환해야 한다.
// 회피 — 컴파일 안 됨open(view.c_str(), O_RDONLY);
// Good — 변환 비용 인지open(std::string(view).c_str(), O_RDONLY);#정리
absl::string_view는 포인터 + 길이만 보유하는 non-owning 참조.- 함수 매개변수에서
const std::string&을 대체해 호출 측 alloc을 제거한다. substr,remove_prefix,remove_suffix가 alloc 없이 view를 재계산한다.- C++17 빌드에서는
std::string_view의 alias가 된다. - null-terminated 보장이 없어 C API에는
std::string변환이 필요하다. - 멤버 변수 보관은 dangling을 부른다.
#다음 편
Part 4-02 — string_view 함정에서 dangling reference, 임시 객체 바인딩, c_str() 변환 비용 등 실전 함정을 본다.
#관련 항목
Abseil Code Review · 20 of 79
- 1 Abseil Code Review — Google production-grade C++ 라이브러리 분석
- 2 Abseil 개요 — Google이 std를 보완한 이유
- 3 Abseil 설계 철학 — std 호환과 추가 기능의 균형
- 4 Abseil 빌드와 의존성 — Bazel vs CMake
- 5 Abseil LTS vs HEAD 릴리스 모델 분석
- 6 Abseil Versioning과 ABI 호환성 정책
- 7 Abseil 매크로 — ABSL_HAVE_*·ABSL_ATTRIBUTE_*
- 8 Abseil ABSL_PREDICT_TRUE/FALSE — branch hint
- 9 absl::LogSeverity — 로그 레벨 타입
- 10 Abseil type_traits — negation·conjunction·void_t
- 11 Abseil Conformance·Policy 분석
- 12 Abseil Memory utilities 분석
- 13 Abseil raw_logging — heap-free 로깅
- 14 Abseil thread_annotations — clang TSA 통합
- 15 absl::Status — exception-free error handling
- 16 absl::StatusOr<T> — 값 또는 에러
- 17 absl status_macros — ASSIGN_OR_RETURN·RETURN_IF_ERROR
- 18 absl::Status payload — 구조화된 에러 컨텍스트
- 19 absl::Status ↔ exception 변환 패턴
- 20 absl::string_view — non-owning 문자열 참조
- 21 absl::string_view 함정 — dangling·c_str·임시 객체
- 22 absl::StrCat — 가변 인자 문자열 연결과 AlphaNum
- 23 absl::StrSplit — Delimiter·Predicate·컨테이너 변환
- 24 absl::StrJoin — 컨테이너 결합과 Formatter
- 25 absl::StrFormat — type-safe printf·FormatSpec
- 26 Abseil ASCII 함수 — locale-free 분류·대소문자 변환
- 27 Abseil Escape — CEscape·HexEscape·Base64
- 28 absl::flat_hash_map — Swiss Table 기반 hash map
- 29 absl::flat_hash_set — set 버전 Swiss Table
- 30 absl::node_hash_map — stable pointer가 필요할 때
- 31 absl::btree_map — sorted·cache-friendly B-tree
- 32 absl::FixedArray — 런타임 크기 stack 배열
- 33 absl::InlinedVector — small buffer optimization
- 34 Abseil Swiss Table internals — control byte·SIMD probing
- 35 absl::Mutex — reader-writer·fairness·deadlock 검출
- 36 absl::Mutex Conditional Critical Section — Await로 cv 없애기
- 37 absl::Notification — once-only signal
- 38 absl::BlockingCounter·Barrier — 다중 thread 조율
- 39 absl::Mutex annotations — clang thread-safety로 race를 컴파일 타임에
- 40 absl::Time·Duration 분석 — 단단한 type
- 41 absl::Time Format·Parse
- 42 absl::CivilTime 분석
- 43 absl::time_zone 분석
- 44 absl::Time mocking — 테스트 친화 시간
- 45 absl::BitGen — 모던 난수 생성기
- 46 Abseil Random Distributions — Uniform·Exponential
- 47 Abseil Mocking Random — 테스트 결정성
- 48 Abseil Random Seeding·Entropy
- 49 absl::int128·uint128 분석
- 50 absl::bits — popcount·countl_zero
- 51 absl::optional vs std::optional
- 52 absl::variant 분석
- 53 absl::span 분석
- 54 absl::any 분석
- 55 absl::compare — three-way 비교
- 56 Abseil utility — apply·in_place
- 57 Abseil AbslHashValue 분석
- 58 Abseil HashState chaining
- 59 Abseil Custom hashable 구현
- 60 Abseil LOG·VLOG·CHECK 분석
- 61 Abseil LogSink 분석
- 62 Abseil LogEntry·structured logging
- 63 Abseil Stack trace·failure_signal_handler
- 64 ABSL_FLAG 정의 분석
- 65 Abseil ParseCommandLine 동작
- 66 Abseil Flag introspection·validation
- 67 Google 스타일의 Abseil 사용 패턴
- 68 Abseil 자주 보는 anti-pattern
- 69 std → absl 마이그레이션 전략
- 70 absl::Cleanup — 함수 종료 시 실행 보장
- 71 Abseil algorithm container 확장 — c_sort·c_find_if·c_count_if
- 72 absl::function_ref와 any_invocable — 함수 객체 전달의 두 축
- 73 absl::bind_front와 Overload — 함수 객체 보조 도구
- 74 absl::Cord — 분산 시스템용 대용량 문자열
- 75 absl::from_chars·SimpleAtoi — 빠른 숫자 변환
- 76 absl::Cord vs std::string — 선택 기준과 메모리 프로파일
- 77 absl::GetStackTrace와 Symbolize — crash 시 readable stack
- 78 absl::ComputeCrc32c — 하드웨어 가속 체크섬
- 79 absl::PeriodicSampler — 적응형 샘플링·jitter 회피
관련 글
absl::StrCat — 가변 인자 문자열 연결과 AlphaNum
Part 4-03: absl::StrCat — variadic 문자열 연결, AlphaNum 어댑터, operator+ / ostringstream과의 성능 차이.
같은 시리즈에서 이어 읽기
absl::PeriodicSampler — 적응형 샘플링·jitter 회피
absl::profiling_internal::PeriodicSampler — sampling rate를 동적으로 조정, geometric distribution으로 jitter 회피. 메모리 할당 추적·profiling 인프라의 기반.
같은 시리즈에서 이어 읽기
absl::from_chars·SimpleAtoi — 빠른 숫자 변환
absl::SimpleAtoi / SimpleAtof / from_chars — locale-free, exception-free, sscanf 대비 10~50배. std::charconv와의 관계.
같은 시리즈에서 이어 읽기
이 글을 참조하는 글 (7)
- absl::Cord vs std::string — 선택 기준과 메모리 프로파일 — Abseil Code Review
- absl::Cord — 분산 시스템용 대용량 문자열 — Abseil Code Review
- absl::span 분석 — Abseil Code Review
- absl::StrSplit — Delimiter·Predicate·컨테이너 변환 — Abseil Code Review
- absl::StrCat — 가변 인자 문자열 연결과 AlphaNum — Abseil Code Review
- absl::string_view 함정 — dangling·c_str·임시 객체 — Abseil Code Review
- absl::Status ↔ exception 변환 패턴 — Abseil Code Review