C++ string 다루기 4

1 분 소요

std::string_view 클래스

C++17 이전에는 읽기 전용 스트링을 받는 함수의 매개변수 타입을 쉽게 결정할 수 없었다. const char*로 지정하면 std::string을 사용하는 클라이언트에서 c_str()나 data()를 이용하여 string을 const char*로 변환해서 호출해야 한다.
이렇게 된다면 string의 객체지향 속성과 여기서 제공하는 뛰어난 헬퍼 메서드를 제대로 활용할 수 없다. 매개변수를 const std::string& 로 지정하면 항상 std::string만 사용해야 하기 때문에 스트링 리터럴의 복사본이 담긴 객체를 생성해서 함수로 전달한다. 이때 오버헤드가 발생한다.
void init(std::string str);
void init(const char* str);
이런 문제로 오버로딩 버전을 만들어 두는데 그리 좋은 방법은 아니다.
C++17부터 추가된 std::string_view 클래스를 사용하면 이러한 고민을 해결할 수 있다. 이 클래스는 std::basic_string_view 클래스 템플릿의 인스턴스로서 <string_view> 헤더에 정의돼 있다. string_view는 실제로 const string& 대신 사용할 수 있고 오버헤드 또한 없다. 다시말해 스트링을 복사하지 않는다.

함수를 다음과 같이 정의하면 모든 종류의 스트링에 적용할 수 있다.
string_view extractExtension(string_view fileName)
{
    return fileName.substr(fineName.rfind('.'));
}
string fileName = R"(c:\temp\my file.ext)";
cout << "C++ string: " << extractExtension(fileName) << endl;
const char* cString = R"(c:\temp\my file.ext)";
cout << "C string: " << extractExtension(fileName) << endl;
cout << "Literal: " << extractExtension(R"(c:\temp\my file.ext)") << endl;
여기서 extractExtension()을 호출하는 부분에서 복제 연산이 하나도 발생하지 않는다. extractExtension() 함수의 매개변수와 리턴 타입은 단지 포인터와 길이만 나타낸다. 그래서 괭장히 효율적이다.

std::string_view 리터럴

표준 사용자 정의 리터럴인 'sv'를 사용하면 스트링 리터럴을 std::string_view로 만들 수 있다.
auto sv = "String view"sv;
표준 사용자 정의 리터럴인 'sv'를 사용하라면 using namespace std::string_vew_literals;using namespace std;를 적어줘야 한다.

참고

  • 전문가를 위한 C++