태그 보관물: api-design

api-design

인터페이스에서 언제 string_view를 사용해야합니까? 코드는 다음과 같이 변경되었습니다. void one_time_setup(const std::string

나는 모방 A와 디자인 된 내부 라이브러리를 사용하고 C ++ 라이브러리를 제안 하고, 언젠가 지난 몇 년 동안 나는 볼의 인터페이스를 사용하여 변경 std::string에를 string_view.

그래서 새로운 인터페이스에 맞게 코드를 정중하게 변경했습니다. 불행히도, 전달해야 할 것은 std :: string 매개 변수이며 std :: string 반환 값입니다. 그래서 내 코드는 다음과 같이 변경되었습니다.

void one_time_setup(const std::string & p1, int p2) {
   api_class api;
   api.setup (p1, special_number_to_string(p2));
}

void one_time_setup(const std::string & p1, int p2) {
   api_class api;
   const std::string p2_storage(special_number_to_string(p2));
   api.setup (string_view(&p1[0], p1.size()), string_view(&p2_storage[0], p2_storage.size()));
}

나는 정말 (아마도 망치)이 변화가 더 많은 코드 이외의 API 클라이언트, 나를 구입 무엇을 볼 수 없습니다. API 호출은 안전하지 않습니다 (API가 더 이상 매개 변수에 대한 스토리지를 소유하지 않기 때문에). 아마도 프로그램 0 작업을 저장했습니다 (컴파일러가 지금 할 수있는 최적화 작업으로 인해). 작업을 저장하더라도 작업을 저장하더라도 시작 후 또는 어딘가에 큰 루프에서 수행되지 않을 두 개의 할당. 이 API에는 해당되지 않습니다.

그러나이 방법은 예를 들어, 내가 다른 곳에서 볼 수 조언을 따르는 것 이 답변 :

따로, C ++ 17부터 std :: string_view를 위해 const std :: string &을 전달하지 않아야합니다.

나는 주로 최적화의 목적으로 비교적 안전한 객체를 덜 안전한 객체 (기본적으로 영광스러운 포인터 및 길이)로 대체하는 것을 옹호하는 것처럼 보이는 충고가 놀랍습니다.

그럼 언제 해야 string_view 사용될 때, 그리고 그것을해야하지?



답변

  1. 가치를 얻는 기능이 문자열의 소유권을 가져야합니까? 그렇다면 std::string(비 const, non-ref)를 사용하십시오. 이 옵션을 사용하면 호출 컨텍스트에서 다시 사용되지 않을 경우 값을 명시 적으로 이동할 수 있습니다.
  2. 기능이 문자열을 읽습니까? 사용 그렇다면 std::string_view때문이다 (CONST, 비-REF) string_view처리 할 수 std::stringchar*문제없이 복사하지 않고 쉽게. 모든 const std::string&매개 변수를 대체해야합니다 .

궁극적으로 생성자 를 호출 할 필요 는 없습니다std::string_view . 변환을 자동으로 처리 std::string하는 변환 연산자 가 있습니다.


답변

A는 std::string_viewa의 몇 가지 이점 제공 const char*++ C에 : 달리를 std::string하는 string_view

  • 기억이 없다
  • 메모리를 할당하지 않습니다
  • 오프셋에서 기존 문자열을 가리킬 수 있으며
  • a보다 포인터 간접 레벨이 하나 낮습니다 std::string&.

즉, string_view는 원시 포인터를 처리하지 않고도 종종 복사를 피할 수 있습니다.

현대 코드에서는 std::string_view거의 모든 const std::string&기능 매개 변수 사용을 대체해야합니다 . std::string변환 연산자를로 선언 하므로 소스 호환 변경 사항이어야합니다 std::string_view.

문자열보기가 문자열 을 만들어야하는 특정 사용 사례 에서 도움 이되지 않는다고해서 그것이 일반적으로 나쁜 생각임을 의미하지는 않습니다. C ++ 표준 라이브러리는 편의성보다는 일반성에 맞게 최적화되는 경향이 있습니다. 문자열보기를 직접 만들 필요가 없으므로 “안전하지 않은”인수는 유지되지 않습니다.


답변

나는 주로 최적화의 목적으로 비교적 안전한 객체를 덜 안전한 객체 (기본적으로 영광스러운 포인터 및 길이)로 대체하는 것을 옹호하는 것처럼 보이는 충고가 놀랍습니다.

나는 이것이 이것의 목적을 약간 오해하고 있다고 생각합니다. “최적화”이지만 실제로는을 사용하지 않아도되는 것으로 생각해야합니다 std::string.

C ++ 사용자는 수십 개의 서로 다른 문자열 클래스를 만들었습니다 . 고정 길이 문자열 클래스, 버퍼 크기가 템플릿 매개 변수 인 SSO 최적화 클래스,이를 비교하는 데 사용되는 해시 값을 저장하는 문자열 클래스 등 일부 사람들은 심지어 COW 기반 문자열을 사용합니다. C ++ 프로그래머가 좋아하는 것이 있다면 문자열 클래스를 작성하는 것입니다.

그리고 그것은 C 라이브러리가 만들고 소유 한 문자열을 무시합니다. 벌거 벗은 char*, 아마 어떤 종류의 크기.

따라서 일부 라이브러리를 작성 중이고를 사용 const std::string&하면 사용자는 이제 사용중인 문자열을 가져 와서에 복사해야합니다 std::string. 아마 수십 번.

std::string의 문자열 별 인터페이스에 액세스하려면 왜 문자열 을 복사 해야 합니까? 그것은 낭비입니다.

string_view매개 변수로 사용 하지 않는 주요 이유 는 다음과 같습니다.

  1. 궁극적 인 목표가 문자열을 NUL 종료 문자열 ( fopen, 등) 을 사용하는 인터페이스로 전달하는 것입니다 . std::stringNUL 종료가 보장됩니다. string_view그렇지 않습니다. 그리고 NUL로 끝나지 않도록 뷰를 서브 스트링하는 것은 매우 쉽습니다. 하위 std::string문자열 a 는 하위 문자열을 NUL 종료 범위로 복사합니다.

    정확히이 시나리오를 위해 특수 NUL 종료 string_view 스타일 유형을 작성했습니다. 대부분의 작업을 수행 할 수 있지만 NUL 종료 상태를 위반하는 작업은 수행 할 수 없습니다 (예 : 끝에서 트리밍).

  2. 평생 문제. 실제로 복사해야 std::string하거나 문자 배열이 함수 호출보다 오래 지속되어야하는 경우을 사용 하여이 상태를 미리 밝히는 것이 가장 좋습니다 const std::string &. 또는 std::string값 매개 변수로 사용하십시오. 이런 식으로 이미 그러한 문자열을 가지고 있다면 즉시 소유권을 주장 할 수 있으며, 발신자가 복사본을 보관할 필요가없는 경우 문자열로 이동할 수 있습니다.


답변