(최신 C++) std::string_view, 왜 사용해야 할까요?

std::string_view

std::string_view란 무엇입니까?

std::string_view C++17부터 추가된 문자열 처리를 위한 매우 강력하고 효율적인 컨테이너입니다.

내부 구현은 다르지만 std::string_view작동 및 기능 std::span거의 같다 std::span이것 std::vectorC 스타일 배열, std::array 다음과 같이 다양한 유형을 효율적으로 처리할 수 있는 배열이 있다면 std::string_viewstd::string, const char *, char () 와 같은 다양한 유형의 문자열을 효율적으로 처리하기 위해 존재합니다.

동시에 std::span(최신 C++) std::span이 궁금하다면 왜 사용해야 할까요?

원래 std::string_view복사 구성이 없기 때문에 원래 문자열에 대한 강력한 참조가 있습니다.

하지만 이미 참조 유형이 있는데 왜 std::string_view필요하세요?그 이유는 C++에서 std::string 다른 다양한 문자열 유형이 있기 때문입니다.

std::string, const char * 및 char()의 차이점

우선 C++에는 위에서 언급한 다양한 유형의 문자열이 있습니다.

std::string사용하기 쉽지만 성능, 사용 편의성, 작업 환경 등에 따라 다릅니다.

std::string때때로 (std::string추상 클래스이기 때문에 메모리 관리 및 멤버 메소드 제공 측면에서 더 편리하지만, 일반적으로 const char * 등), 불행히도 성능이나 메모리 사용량 측면에서. std::string, const char *, char () 그들은 모두 내부 구현이 약간 다릅니다.

예를 들어 std::string str1 = "script by";선언하면 std::string형제 str1script by 문자열을 가리킬 것입니다.

이때 script by크기에 따라 문자열이 힙 메모리 영역에 올라가는지 아니면 스택 메모리 영역에만 올라가는지에 따라 다릅니다.

.

동시에 const char * str2 = "nx006";선언하면 nx006호출된 문자열은 읽기 전용 저장소에 업로드됩니다.

그리고 str2읽기 전용 메모리 영역의 문자열을 가리킵니다.

마침내 char() str3 = "CODE EDGE;" 선언하면 CODE EDGE호출된 문자열은 스택 메모리 영역에 올라갑니다.

그리고 str3이 문자열을 가리킬 것입니다.

기존 문자열 처리 문제

아래 코드를 살펴보겠습니다.

이 코드는 아나그램에 대한 해시를 생성합니다.

// anagram hash generator
std::string anagram_hash(const std::string& str)
{
    std::map<char, int> alphabet_tables;
    std::ranges::for_each(str, (&alphabet_tables)(const auto& c) {alphabet_tables(c)++; });
    std::string hash = "";
    for (const auto& (alphabet, number) : alphabet_tables) {
        hash += alphabet;
        hash += std::to_string(number);
    }

    return std::move(hash);
}

위 코드에서 파라미터 값의 타입으로 const std::string& str다음과 같이 main 함수에서 문자열을 전달한다고 가정해 봅시다.

int main  ()
{
    std::string str1 = "AABBC";
    const char * str2 = "AABBC";
    char() str3 = "AABBC";

    const auto hash1 = anagram_hash(str1);
    const auto hash2 = anagram_hash(str2);
    const auto hash3 = anagram_hash(str3);

    std::cout << hash1 << '\n'
              << hash2 << '\n'
              << hash3 << '\n';
    return 0;
}

결과:

A2B2C1
A2B2C1
A2B2C1

위의 코드에는 세 개의 입력이 필요합니다.

str1, str2, str3나는 행동해야 한다.

그런데 자세한 동작 순서를 살펴보면 예상치 못한 동작이 발생한 것을 알 수 있습니다.

std::string str1이를 위해 문제없이 작동합니다.

매개변수 유형은 참조 유형이므로 복사 생성자 없이 매개변수를 함수에 전달할 수 있습니다.


하지만 const char * str2그리고 char() str3문제는 통과되면 내부 std::string다음 유형의 임시 개체를 만든 후 str2그리고 str3복제를 위한 복제 구조입니다.

그리고 복사된 메모리 str그것을 가리킬 것입니다.

의도하지 않은 복사 생성자가 호출되어 성능이 저하되었습니다.

std::string_view 사용

이것을 해결하기 위해 우리는 std::string_view매개변수 유형을 조정할 수 있습니다.

std::string anagram_hash(const std::string_view str)
{
    std::map<char, int> alphabet_tables;
    std::ranges::for_each(str, (&alphabet_tables)(const auto& c) {alphabet_tables(c)++; });
    std::string hash = "";
    for (const auto& (alphabet, number) : alphabet_tables) {
        hash += alphabet;
        hash += std::to_string(number);
    }

    return std::move(hash);
}

매개변수 유형 std::string&존재하다 std::string_view로 변경하면 str2, str3사용하는 경우에도 실수로 임시 개체의 복사본을 만들지 않고 함수 내에서 직접 원래 문자열을 참조할 수 있습니다.

std::string_view매우 강력한 기능이며 구문을 이식하기 쉽기 때문에 적극적으로 사용할 수 있습니다.

std::string_view 사용 시 고려 사항

std::string_view참조 유형입니다.

즉, 원본이 변경된 경우 std::string_view또한 변경됩니다.

원래 메모리가 수명이 다해 파괴되면 std::string_view 또한 쓰레기 값을 가리킬 것입니다.

그러므로 std::string_view 또한 다른 참조형과 마찬가지로 기본형과 수명형을 벗어나지 않도록 주의해야 합니다.