c++17에 string_view라는 기능이 추가되었다. 이 기능을 사용하면 좋은 점을 예시로 살펴보자
// 원래 사용하던 방식
std::string FiveCharacterOnlyString(const std::string& str)
{
if (str.size() < 5) return str;
return str.substr(0, 5);
}
// c++ 17 string_view
// string_view를 사용하면 string 객체의 복사가 발생하지 않습니다.
std::string_view FiveCharacterOnlyStringView(const std::string_view str)
{
if (str.size() < 5) return str;
return str.substr(0, 5);
}
int main()
{
// std::string val1 = "12345"
auto val1 = FiveCharacterOnlyString("123456789");
// std::string_view val2 = "12345"
auto val2 = FiveCharacterOnlyStringView("123456789");
}
FiveCharacterOnlyString(const std::string& str) 함수의 인자로 C 문자열 리터럴("123456789"처럼 ""로 둘러싸인 문자들을 보고 C 문자열 리터럴이라고 함)을 넘겨주면 const & 타입으로 인자를 넘겨도 어쩔 수 없이 내부적으로 복사가 일어난다.
복사가 일어나는 이유는 문자열 리터럴 C++에서 string 클래스에 const char*를 받는 생성자가 있다. 생성자가 호출되면서 string의 메모리 할당과 const char* -> string으로 복사가 발생한다는 것이다.
"123456789"는 한번만 쓰고 소멸될 임시 객체인데 복사 되는 것은 명백히 낭비이다.
이런 상황에서 string_view를 사용하면 복사 없이 메모리 할당과 복사 없이 인자를 전달할 수 있다.
타입
string_view 타입들은 내부적으로 std::basic_string_view<T>로 구현되어 있다. const char* 타입처럼 basic_string_view는 문자열의 시작을 가리키는 객체이면서 동시에 문자열의 길이까지 기억하는 클래스 템플릿. 자세한 설명은 여기 참고
이름 | 타입 |
string_view | std::basic_string_view<char> |
wstring_view | std::basic_string_view<wchar_t> |
u16string_view | std::basic_string_view<char16_t> |
u32string_view | std::basic_string_view<char32_t> |
사용 예시
신기한 점은 sv5는 출력하면 예상했던대로 "12"만 출력되는데, sv5.data()를 출력하면 그대로 "123456"이 모두 출력된다. 디버그 모드로 sv5를 보면
sv5의 내부 data는 여전히 "123456"이고 size만 2이다. 아무리 처음에 초기화할 때 2번째 인자로 일정 개수를 넣어줘도 내부적으로 Mydata는 const char* 타입이고, 따라서 null terminated 문자열이다. data함수는 이 Mydata라는 const char*를 리턴하고 당연히 null character를 만나기 전 모든 문자열을 출력하므로 "123456" 전부를 출력한다.
사용 시 주의할 점
string_view는 문자열 포인터를 Data로 갖고 있으므로, sv5에 할당해준 원본 문자열 str을 수정하면 string_view의 Data도 같이 변한다. 그런데 Size는 초기에 할당해준 5가 그대로이다. 두 멤버가 불일치함으로써 문제가 생길 수 있다.
Reference
https://jungwoong.tistory.com/56
https://linkmemo.tistory.com/215
'공부 > C || C++' 카테고리의 다른 글
C++ 클래스 상속, 다중 상속, 가상 함수 그리고 다형성(Inheritance & virtual function & polymorphism) (1) | 2022.09.25 |
---|---|
static 변수와 전역 변수와 비교 (0) | 2022.09.23 |
C++ vector::push_back vs vector::emplace_back (0) | 2022.09.18 |
STL Container (시퀀스 컨테이너, 연관 컨테이너, 컨테이너 어댑터) (0) | 2022.09.17 |
C++ std::move (0) | 2022.09.05 |