전역 const char []를 constexpr string_view로 바꾸어야 할 문제가 있습니까?


17

우리 팀은 10 년 이상 된 C ++ 코드 기반으로 작업하고 있으며 최근에는 C ++ 17 컴파일러로 전환했습니다. 그래서 우리는 코드를 현대화하는 방법을 찾고 있습니다. YouTube에서 열린 컨퍼런스 토크에서 const char*전 세계 문자열을 로 바꾸 겠다는 제안을 들었습니다 constexpr string_view.

우리는 const char*코드에 많은 수의 전역 문자열 상수를 가지고 있기 때문에 알아야 할 잠재적 문제가 있는지 묻고 싶습니다.

답변:


15

이러한 문제는 다음과 같은 사항을 알고 있어야합니다.

  1. std::string_view종료 할 필요는 없습니다 null. 따라서 일부 const char*string_view대체하고 이전에 종료 된 하위 문자열 의 구성을 via로 null바꾸면 기본 포인터를 종료 문자열 을 기대하는 API에 전달할 수 없습니다 . 예 (UB가 없지만 쉽게 구성 할 수 있음) :char*string_viewstd::string_view::substrnull

    void legacy(const char *str) {
       std::printf("%s\n", str);
    }
    
    constexpr std::string_view sv1 = "abcde";
    constexpr std::string_view sv2 = sv1.substr(0, 2); // view on "ab"
    
    legacy(sv2.data()); // Not intended: prints "abcde" 
    
  2. 당신이 암시를 구성 할 수 있지만 std::stringA로부터 const char*, 당신은에 그렇게 할 수 없습니다 std::string_view. 아이디어는 표지 아래에서 깊은 복사가 발생하지 않아야하며 명시 적으로 요청 된 경우에만 발생해야합니다. 예:

    std::map<std::string, int> m;
    constexpr std::string_view sv = "somekey";
    constexpr const char *old = "somekey";
    
    m[old] = 42; // works as expected
    m[sv] = 42; // fails to compile
    m[std::string(sv)] = 42; // be explicit, this is ok
    

    const char*프로젝트에서 글로벌 인스턴스 의 기존 사용법에 따라이 동작을 수행하려면 다양한 위치에서 수동 개입이 필요할 수 있습니다.


0이 아닌 종료는 확실히 문제입니다. 이제 SV를 거쳐야합니다. std::string(sv).c_str()대신 API로 전달하려고 한다고 가정 합니까?
darune

@darune 옵션이지만 API의 수명 가정을 확인해야합니다. 당신이 가서이 someLegacyFct(std::string(sv).c_str())백엔드가 어떻게 든 포인터를 저장한다면 ...
lubgr

그것은 정확합니다 – 단지 그 생애 가정과 함께
darune

두 번째 문제는 "운이 좋게"우리에게 큰 문제가되지 않을 것입니다. 우리 회사 프레임 워크에는 명시 적 const char*생성자 가있는 자체 문자열 클래스 (알고 있습니다 ...)가 있습니다. 따라서 명시적인 std::stringfrom의 string_view구성은 우리의 경우에 일관됩니다.
PixelSupreme
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.