string_view는 c++ 17에서 추가되었습니다. 

 string_view는 다양한 문자열 타입을 전달 받을 수 있는 안전하면서 효과적인 방법을 제공합니다. 

 내부적으로 문자열에 대한 pointer와 길이만 가지므로 임시객체를 생성하지 않고 문자열을 

 사용 할 수 있습니다. 

 주의 할점은 string_view는 내부적으로 null 종료 문자를 가지지 않습니다. 

 (사실 string 타입류는 size를 들고 있기 때문에 null문자가 없어도 됩니다. )

 또한 원본 데이터에 대한 변경을 방지합니다.

 string_view를 사용시에 주의 할 점은 원본 데이터에 대한 객체의 수명을 제어 할 수 없기 때문에

 호출 하는 주체가 원본 데이터의 안정성을 보장 해 줘야 합니다.

 string_view는 암시적 변환이 지원되면 template을 사용하지 않고도 다양한 타입의 문자열을 전달 받아 사용할 수

 있습니다.

string_view 기본 타입

 string_view 타입들을 내부적으로 std::basic_string_view<T>로 구현되어 있습니다. 

이 름 설 명
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>

string_view를 사용하기 위한 Visual Studio 2019 셋팅

 vs2019의 경우 기본값이 c++14로 설정되어 있습니다. string_view를 사용하기 위해서는

 c++17이 지원되도록 환경 설정을 변경해야합니다.

 솔루션 탐색기 -> 프로젝트 우클릭 -> 구성 속성 -> 일반 -> C++ 언어 표준 변경을 C++ 17로 변경합니다.

C++ 17을 지원하도록 변경하기

sring_view 사용하기

sring_view는 2가지 방법으로 사용 할 수 있습니다. 

  • 문자열 전체 전달
  • 문자열의 부분 전달
int main() {
    // 전체 문자열 전달
    std::string_view sv1("123456789");
    copy(sv1.begin(), sv1.end(), ostream_iterator<char>(cout)); //  123456789 출력
    cout << '\n';
    cout << sv1.data() << '\n';  // 123456789 출력

    // 부분 문자열 전달
    std::string_view sv2("123456789", 2);
    copy(sv2.begin(), sv2.end(), ostream_iterator<char>(cout)); // 12 출력
    cout << '\n';

    // data함수를 사용하면 const char *를 리턴하기 때문에 '\0' 까지 출력
    // 부분 문자열을 사용하려면 begin(), end()형태로 사용 필요
    cout << sv2.data() << '\n';  // 123456789 출력

sring_view 장점

// c++ 14버전
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);
}

// std::string val1 = "12345"
auto val1 = FiveCharacterOnlyString("123456789");
// std::string_view val2 = "12345"
auto val2 = FiveCharacterOnlyStringView("123456789");

 예제를 보시면 std::string으로 구현 된 FiveCharacterOnlyString를

 std::string_view로 구현 된 FiveCharacterOnlyStringView 함수로 대체 할 수 있습니다. 

 FiveCharacterOnlyString를 사용하게 되면 std::string타입의 복사본이 생성되게 됩니다. 

 FiveCharacterOnlyStringView를 사용하게 되면 복사본 생성 없이 효율적으로 동작할 수 있도록 지원합니다. 

void UsedString(std::string & str)
{
    // string 원본 객체에 대한 변경이 이루어 집니다.
    str = "실수로 데이터 변경 시도";
}

void UsedStringView(std::string_view str_v)
{
    // string_view 원본 객체에 대한 변경이 발생하지 않습니다. 
    str_v = "실수로 데이터 변경 시도";
}

 추가적으로 std::string_view를 사용하게 되면 실수로 데이터를 변경을 해도 전달 받은 원본 객체에 대해서 

 안전하게 사용 할 수 있습니다.

 또한 std::string이 지원하는 다양한 멤버함수를 std::string_view도 지원하기 때문에 손쉽게 사용 할 수 있습 니다.

void CallerOriginStringObject(std::string_view str_v, std::string& str)
{
    std::cout << "[origindata] str_v = " << str_v.data() << " Size = " << str_v.size() << std::endl;
    str = "modify";
    // 원본데이터가 변경되면 string_view의 데이터가 변경됩니다.
    // 문자열 : "modify", size = 15
    // 남아있는 빈 공간에는 이전 데이터가 들어 있습니다. 
    std::cout << "[origindata modify] str_v = " << str_v.data() << " Size = " << str_v.size() << std::endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::string str("original string");
    CallerOriginStringObject(str, str);
}

변경된 상태의 string_view
결과내용

 위에서도 설명했듯이 string_view 자체는 원본 데이터를 수정 할 수 없지만

 바라보고 있는 원본 데이터가 수정되면 string_view 문자열 데이터도 수정됩니다. 

 주의할 점은 size 정보는 처음 원본데이터를 할당 받을 당시의 size로 고정되어 있기 때문에 예상하지 않은 동작이 

 발생 할 수 있습니다.

 그렇기 때문에 string_view를 사용 도중에는 호출하는 입장에서 원본 데이터가 수정되지 않을 것을 보장해줘야 합니다.

내부 동작 방식 

 std::string_view가 구현된 소스 코드를 확인 해 보면 basic_string_view 이라는 템플릿 클래스로 구현된 것을 확인

 할 수있습니다.

객체의 사이즈 

template <class _Elem, class _Traits>
class basic_string_view { // wrapper for any kind of contiguous character buffer
//... 생략 
private:
//... 생략 
    const_pointer _Mydata;
    size_type _Mysize;
}

 basic_string_view는 내부적으로 문자열 포인터와 사이즈를 저장하는 변수만을 가집니다. 

 문자나 std::string 타입보다 가볍게 동작 할 수 있습니다. 

 const_point 형태로 보유하기 때문에 원본 데이터를 수정 할 수 없고 읽기 전용으로만 사용 가능 합니다.

 

변 수 타 입 설   명
_Mydata const_point 템플릿 인자로 입력받은 문자열 포인터의 const형 포인터를 가집니다. 
_Mydata는 전달 받은 문자형 데이터의 배열 [0]의 위치를 가집니다. 
_Mysize size_type = size_t 전달 받은 문자형 데이터의 사이즈를 저장합니다. 

객체 생성 및 할당 방식 

template <class _Elem, class _Traits>
class basic_string_view { // wrapper for any kind of contiguous character buffer
//... 생략 
constexpr basic_string_view() noexcept : _Mydata(), _Mysize(0) {}

constexpr basic_string_view(const basic_string_view&) noexcept = default;

constexpr basic_string_view& operator=(const basic_string_view&) noexcept = default;

constexpr basic_string_view(_In_z_ const const_pointer _Ntcts) noexcept 
: _Mydata(_Ntcts), _Mysize(_Traits::length(_Ntcts)) {}

constexpr basic_string_view(_In_reads_(_Count) const const_pointer _Cts, const size_type _Count) noexcept // strengthened
: _Mydata(_Cts), _Mysize(_Count) {
#if _CONTAINER_DEBUG_LEVEL > 0
        _STL_VERIFY(_Count == 0 || _Cts, "non-zero size null string_view");
#endif // _CONTAINER_DEBUG_LEVEL > 0
    }
private:
//... 생략 
}

 string_view의 생성자 동작 방식을 확인 해 보면 매우 간단한데 전달 받은 문자열 데이터의 포인터 및 사이즈를

 저장합니다. 

문자열 배정시 string_view 객체 상태

 그림과 같이 문자열에 대한 데이터를 설정합니다. 설정 비용은 pointer하나와 size_t 변수 값에 대한 변경 만으로

 가능 합니다. 

새로운 문자열 배정시 string_view 객체 상태

 string_view에 새로운 문자열을 배정하면 그림과 같이 새로운 문자열을 바라보도록 데이터를 셋팅합니다.

string_view 관련 참조 사이트

https://docs.microsoft.com/en-us/cpp/standard-library/string-view?view=vs-2019

 

 

In this article --> Defines the class template basic_string_view and related types and operators. (Requires compiler option std:c++17 or later.) Syntax #include The string_view family of template specializations provides an efficient way to pass a read-onl

docs.microsoft.com

https://en.cppreference.com/w/cpp/string/basic_string_view

 

std::basic_string_view - cppreference.com

template<     class CharT,     class Traits = std::char_traits > class basic_string_view; (since C++17) The class template basic_string_view describes an object that can refer to a constant contiguous sequence of char-like objects with the first element of

en.cppreference.com

 

'c++ > modern c++' 카테고리의 다른 글

[c++] std::lock 관련 함수들  (0) 2020.05.22
[c++] std::mutex  (0) 2020.03.28
[c++] constexpr 키워드  (0) 2020.03.19
[c++] auto와 decltype 키워드  (0) 2020.03.15
[c++] std::move와 std::forward  (4) 2020.03.07

+ Recent posts