Abseil Tip #1: string_view
의 활용 방법과 이점
string_view
란 무엇이고, 왜 중요한가?
C++에서 문자열을 인자로 받는 함수를 작성할 때, 주로 다음 세 가지 방식 중 하나를 사용합니다:
- C 스타일 방식
void TakesCharStar(const char* s);
- 이전 C++ 표준 방식
void TakesString(const std::string& s);
- C++17 이후 도입된
string_view
방식- Abseil 라이브러리 사용:
absl::string_view
- C++17 표준 사용:
std::string_view
void TakesStringView(absl::string_view s); void TakesStringView(std::string_view s);
- Abseil 라이브러리 사용:
문제점 및 string_view
도입 이유
const char*
를std::string
으로 변환할 때에는 추가적인 변환 비용이 발생하며, 반대로std::string
을const char*
로 변환할 때에는c_str()
메서드를 사용해야 합니다.string_view
를 사용하면 이러한 변환 비용을 줄이고 더 효율적으로 문자열을 처리할 수 있습니다.
string_view
의 특징
string_view
는 문자열 데이터를 소유하지 않는 가벼운 뷰입니다. 즉, 기존의 문자 버퍼를 참조할 뿐 복사하지 않으며, 포인터와 길이 정보만 저장합니다.string_view
는const char*
및const std::string&
에서 암시적으로 변환할 수 있으며, 이 경우 추가적인 메모리 할당이 필요하지 않습니다.void AlreadyHasString(const std::string& s) { TakesStringView(s); // 변환 없이 사용 가능 } void AlreadyHasCharStar(const char* s) { TakesStringView(s); // 복사 없이 효율적 }
- 주의 사항:
string_view
는 데이터를 소유하지 않기 때문에,string_view
가 참조하는 원본 문자열의 수명이string_view
보다 길어야 합니다.
언제 string_view
를 사용해야 하는가?
- 단기적인 참조에 적합: 함수 내부에서만 사용하거나 수정이 필요 없는 데이터를 처리할 때 유용합니다.
- 만약 데이터를 나중에 사용하거나 수정해야 한다면,
std::string
으로 명시적으로 변환해야 합니다.std::string my_string_copy = std::string(my_string_view);
string_view
를 데이터 저장 용도로 사용하는 것은 권장되지 않습니다. 예를 들어, 다음과 같은 구조체 정의는 좋지 않은 예입니다:struct TestScore { absl::string_view username; // `std::string`으로 대체하는 것이 좋습니다 double score; };
추가 팁
string_view
는 작은 값이므로 함수 인자로 전달할 때 값 복사(pass by value) 방식이 권장됩니다.string_view
는 NUL 종료되지 않은 문자열을 처리하므로,printf("%s\n", sv.data());
와 같은 방식으로 출력하는 것은 안전하지 않습니다.absl::PrintF("%s\n", sv);
string_view
는 로그 출력에서도 사용할 수 있습니다:LOG(INFO) << "Took '" << sv << "'";
- 기존 코드에서
const std::string&
나const char*
를 받는 함수를string_view
로 변경할 경우, 대부분 안전하게 사용할 수 있지만, 함수 포인터를 사용하는 경우 타입 불일치 문제가 발생할 수 있습니다. string_view
는 constexpr 생성자와 단순한 소멸자를 가지므로, 전역 변수나 상수로 사용할 때 유용합니다.
결론
string_view
는 C++에서 효율적으로 문자열을 다룰 수 있는 도구로, 특히 기존의 const char*
와 std::string
방식의 단점을 보완합니다. 다만, 데이터의 수명 관리가 중요하기 때문에, 적절한 상황에서 사용하는 것이 필요합니다.
reference
https://github.com/abseil/abseil.github.io/blob/master/_posts/2017-09-26-totw-1.md