Abseil Tip 1 string_view의 활용 방법과 이점

Abseil Tip #1: string_view의 활용 방법과 이점

string_view란 무엇이고, 왜 중요한가?

C++에서 문자열을 인자로 받는 함수를 작성할 때, 주로 다음 세 가지 방식 중 하나를 사용합니다:

  1. C 스타일 방식
    void TakesCharStar(const char* s);
    
  2. 이전 C++ 표준 방식
    void TakesString(const std::string& s);
    
  3. 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);
      

문제점 및 string_view 도입 이유

  • const char*std::string으로 변환할 때에는 추가적인 변환 비용이 발생하며, 반대로 std::stringconst char*로 변환할 때에는 c_str() 메서드를 사용해야 합니다.
  • string_view를 사용하면 이러한 변환 비용을 줄이고 더 효율적으로 문자열을 처리할 수 있습니다.

string_view의 특징

  • string_view문자열 데이터를 소유하지 않는 가벼운 뷰입니다. 즉, 기존의 문자 버퍼를 참조할 뿐 복사하지 않으며, 포인터와 길이 정보만 저장합니다.
  • string_viewconst 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;
    };
    

추가 팁

  1. string_view는 작은 값이므로 함수 인자로 전달할 때 값 복사(pass by value) 방식이 권장됩니다.
  2. string_viewNUL 종료되지 않은 문자열을 처리하므로, printf("%s\n", sv.data());와 같은 방식으로 출력하는 것은 안전하지 않습니다.
    absl::PrintF("%s\n", sv);
    
  3. string_view로그 출력에서도 사용할 수 있습니다:
    LOG(INFO) << "Took '" << sv << "'";
    
  4. 기존 코드에서 const std::string&const char*를 받는 함수를 string_view로 변경할 경우, 대부분 안전하게 사용할 수 있지만, 함수 포인터를 사용하는 경우 타입 불일치 문제가 발생할 수 있습니다.
  5. string_viewconstexpr 생성자와 단순한 소멸자를 가지므로, 전역 변수나 상수로 사용할 때 유용합니다.

결론

string_view는 C++에서 효율적으로 문자열을 다룰 수 있는 도구로, 특히 기존의 const char*std::string 방식의 단점을 보완합니다. 다만, 데이터의 수명 관리가 중요하기 때문에, 적절한 상황에서 사용하는 것이 필요합니다.

reference

https://github.com/abseil/abseil.github.io/blob/master/_posts/2017-09-26-totw-1.md