먼저 알아야 할 개념 : 문자열 리터럴
overview
std::string_view 클래스는 "문자열에 대한 비소유 참조" 이다
문자열에 대한 "상수 참조" 또는 "읽기 전용 참조" 라고 할 수도 있지만,
const std::string& 로 오해할 수 있기 때문에 이렇게 정의한다.
실질적인 기능을 제공하는 것은 std::basic_string_view라는 템플릿이다.
std::string_view는 미리 정의된 std::basic_string_view<char>의 별칭일 뿐..(std::basic_string 을 std::string으로 쓰는것과 유사)
std::string
- C Style 문자열 표현
- 문자열의 마지막에 널문자(\0)를 붙여서 끝남을 표시함
- std::string
- <string> 헤더에 정의
- 비교연산자
- 연산자 오버로딩
- == , != , < 와 같은 연산자를 사용할 수 있음
- compare 메소드 사용가능
- cpp 20부터는 3-way 비교연산자로 수행 가능
- 연산자 오버로딩
- 메모리 관리
- string클래스에서 알아서 해줌 -> 메모리 오버런 걱정 없음
- 자세히 보자면...
- string을 할당하거나, 크기 변경 코드가 여기저기 있더라도 메모리 누수가 발생하지 x
- string객체는 모두 스택변수이기 때문에 생성된 스코프를 벗어나면 알아서 소멸자에서 정리
- 연산자를 원하는 방식으로 동작할 수 있음
- string을 할당하거나, 크기 변경 코드가 여기저기 있더라도 메모리 누수가 발생하지 x
- 자세히 보자면...
- string클래스에서 알아서 해줌 -> 메모리 오버런 걱정 없음
- c_str() 메소드를 사용하면 C언어에서 호환되는 const char 포인터를 얻을 수 있음
- but 리턴된 const포인터는 string에 대한 메모리를 재할당하거나 해당 객체를 제거하면 유효치 않음
- 현재 string에 담긴 내용을 정확히 사용하려면 이 메소드를 호출한 직후에 리턴된 포인터를 바로 활용
- 함수 안에서 생성된 스택 기반의 string 객체에 대해서 c_str()을 호출한 결과를 절대로 리턴값으로 전달하면 안된다.
std::string_view
만약 읽기 전용 문자열을 매개변수로 받는 함수를 작성한다면, 해당 문자열에 대한 타입은 어떻게 정하겠는가?
- const char* 로 지정한다면, std::string을 사용하는 클라이언트에서 c_str()나 data()를 사용하여 string을 const char*로 변환해서 호출해야 하는 단점이 있다.
- const std::string& 으로 지정한다면, 항상 std::string만 사용해야한다.
- 예를 들어 문자열 리터럴을 전달하면 컴파일러는 그 문자열 리터럴의 복사본이 담긴 string 객체를 생성하여 함수로 전달하기 때문에 오버헤드가 발생된다
즉, 이 클래스의 주된 용도는 const string&을 대신하는 것 이다!
만약 아래와 같은 함수가 있다고 치자.
void A(const string& str)
{
cout<<str;
}
void B(const char* str)
{
cout<<str;
}
위 A() B() 모두 단순히 문자열을 입력받아 출력하는 함수이다
std::string str = "hello";
A("hi");
B(str.c_str());
하지만 이렇게 호출한다면, 둘 다 위에서 말한 문제가 발생한다.
- A("hi")의 경우에는 결국 const char*로 간주되며, string(const char*) 생성자가 실행되어 메모리 할당과 문자열 자료 복사가 발생한다.
- B(str.c_str())의 경우에는 string을 사용하기 때문에 변환해서 매개변수에 넣어주어야한다.
void C(const string_view& str)
{
cout<<str;
}
이렇게 선언한다면 두가지 다 필요 없지롱!
또 주목할 점은 아래의 몇가지가 있다
- 연산자 오버로딩 지원
- c_str()함수가 없다
- data()가 돌려주는 것이 종료 문자열이 아니다
- string_view만의 인터페이스가 추가 되었다
- remove_prefix 및 remove_suffix
- cpp 17에서 string_view를 위한 문자열 리터럴을 추가했다!
- "hi"sv 처럼 끝에 접미사 sv가 붙은 문자열 리터럴은 상수 string_view객체가 된다
참고 사항
https://en.cppreference.com/w/cpp/string/basic_string_view
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3921.html
https://junstar92.tistory.com/305
'Programming > C++' 카테고리의 다른 글
[cpp][c++11] 타입 추론 (type inference) (0) | 2022.12.16 |
---|---|
[cpp][c++11] noexcept 키워드 (0) | 2022.12.16 |
[cpp] 전방 선언에 대하여 (0) | 2022.12.02 |
[cpp][effective_c++_19] 클래스 설계는 타입 설계와 똑같이 (0) | 2022.12.01 |
[cpp][effective_c++_18] 인터페이스 설계는 쓰기엔 쉽게, 엉터리로 쓰기엔 어렵게 (0) | 2022.11.23 |