공부/C || C++

C++17 string_view

sudo 2022. 9. 19. 22:48

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으로 복사가 발생한다는 것이다.

https://cplusplus.com/reference/string/string/string/

"123456789"는 한번만 쓰고 소멸될 임시 객체인데 복사 되는 것은 명백히 낭비이다.

 

이런 상황에서 string_view를 사용하면 복사 없이 메모리 할당과 복사 없이 인자를 전달할 수 있다. 

 

타입

string_view 타입들은 내부적으로 std::basic_string_view<T>로 구현되어 있다. const char* 타입처럼 basic_string_view는 문자열의 시작을 가리키는 객체이면서 동시에 문자열의 길이까지 기억하는 클래스 템플릿. 자세한 설명은 여기 참고

https://modoocode.com/239

 

C++ 레퍼런스 - basic_string_view

 

modoocode.com

이름 타입
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 

 

[c++17] string_view

 string_view는 c++ 17에서 추가되었습니다.  string_view는 다양한 문자열 타입을 전달 받을 수 있는 안전하면서 효과적인 방법을 제공합니다.  내부적으로 문자열에 대한 pointer와 길이만 가지므로 임

jungwoong.tistory.com

https://linkmemo.tistory.com/215

 

C++ string_view의 이해와 활용

string_view는 C++ 17에 추가된 클래스로 문자열에 대한 참조라고 볼 수 있습니다. 사용법은 string과 유사하며 장점은 string에 비하여 적은 메모리 사용량과 연산 성능에 대한 이점을 가지고 있습니다.

linkmemo.tistory.com

https://occamsrazr.net/tt/316

 

C++17 표준 라이브러리의 std::string_view 소개

조만간 공식화될 C++17에 추가된 std::string_view를 소개합니다.

occamsrazr.net