string :: c_str ()은 C ++ 11에서 더 이상 null로 끝나지 않습니까?
C ++ 11 basic_string::c_str
에서는와 정확히 동일하게 정의되며 basic_string::data
, 이는 *(begin() + n)
및 *(&*begin() + n)
(when 0 <= n < size()
) 과 정확히 동일하도록 정의됩니다 .
문자열 끝에 항상 null 문자가 있어야하는 것을 찾을 수 없습니다.
이것은 c_str()
더 이상 null로 끝나는 문자열을 생성하지 않는다는 것을 의미합니까 ?
이제 내부적으로 널 종료 버퍼를 사용하려면 문자열이 필요합니다. operator[]
(21.4.5) 의 정의를보십시오 .
필요 :
pos <= size()
.반환 값 :
*(begin() + pos)
ifpos < size()
, 그렇지 않으면T
값 이있는 유형의 객체에 대한 참조charT()
; 참조 된 값은 수정되지 않습니다.
c_str
(21.4.7.1/1)을 돌아 보면 다음과 같이 정의되어 있음을 알 수 있습니다 operator[]
.
반환 값 : 포인터
p
등이p + i == &operator[](i)
각i
에서[0,size()]
.
모두 c_str
와 data
구현을 효과적으로 이용 널 종료 버퍼 강제하므로, O (1)이 요구된다.
또한 David Rodríguez-dribeas 가 주석에서 지적했듯이 반환 값 요구 사항은 또한에 &operator[](0)
대한 동의어로 사용할 수 있음을 의미 c_str()
하므로 종료하는 null 문자는 동일한 버퍼에 *(p + size())
있어야합니다 (과 같아야합니다 charT()
). 이는 또한 터미네이터가 느리게 초기화 되더라도 중간 상태에서 버퍼를 관찰 할 수 없음을 의미합니다.
사실 새로운 표준은 .data ()와 .c_str ()이 이제 동의어라고 규정 한 것이 사실입니다. 그러나 .c_str ()이 더 이상 0으로 끝나지 않는다고 말하지 않습니다. :)
이는 이제 .data ()가 0으로 끝나는 것에 의존 할 수 있음을 의미합니다.
Paper N2668은 std :: basic_string의 c_str () 및 data () 멤버를 다음과 같이 정의합니다.
const charT* c_str() const; const charT* data() const;
반환 값 : 첫 번째 size () 요소가 * this로 제어되는 문자열의 해당 요소와 같고 마지막 요소가 charT ()에 의해 지정된 널 문자 인 길이 size () + 1 배열의 초기 요소에 대한 포인터.
요구 사항 : 프로그램은 문자 배열에 저장된 값을 변경하지 않아야합니다.
이것은 std :: string이 포함 된 null을 포함 할 수 있기 때문에 유효한 std :: string이 C-string으로 취급 될 수 있다는 것을 의미 하지 않습니다 . 이는 const char *로 직접 사용될 때 C-string을 조기에 종료합니다.
추가:
C ++ 11 의 실제 게시 된 최종 사양에 대한 액세스 권한이 없지만 실제로 사양의 개정 내역 어딘가에 단어가 삭제 된 것으로 보입니다. 예 : http://www.open-std.org/jtc1/ sc22 / wg21 / docs / papers / 2011 / n3242.pdf
§ 21.4.7 basic_string 문자열 작업
[string.ops]
§ 21.4.7.1 basic_string 접근 자
[string.accessors]
const charT* c_str() const noexcept; const charT* data() const noexcept;
- 반환 값 : 포인터 P 등이
p + i == &operator[](i)
각각i
에서[0,size()]
.- 복잡성 : 일정한 시간.
- 요구 사항 : 프로그램은 문자 배열에 저장된 값을 변경하지 않아야합니다.
"역사"는 오래 전 모든 사람이 단일 스레드에서 작업했거나 적어도 스레드가 자체 데이터를 가진 작업자 였을 때 C ++ 용 문자열 클래스를 설계하여 이전보다 쉽게 문자열을 처리 할 수 있었으며 오버로드되었습니다. 연산자 +는 문자열을 연결합니다.
문제는 사용자가 다음과 같은 작업을 수행한다는 것입니다.
s = s1 + s2 + s3 + s4;
그리고 각 연결은 문자열을 구현해야하는 임시를 만듭니다.
따라서 누군가는 내부 표현을 연속 버퍼로 변경하는 C- 문자열로 읽고 싶을 때까지 내부적으로 모든 문자열과 함께 일종의 "로프"를 저장할 수있는 "지연 평가"라는 뇌파를 가졌습니다. .
이것은 위의 문제를 해결했지만 특히 .c_str () 작업이 읽기 전용 일 것으로 예상하거나 아무것도 변경하지 않으므로 아무것도 잠글 필요가없는 멀티 스레드 세계에서 다른 골칫거리가되었습니다. 누군가가 다중 스레드를 수행하는 경우 (스레딩 표준조차 없었을 때) 클래스 구현에서 조기 내부 잠금도 좋은 생각이 아닙니다. 사실 매번 단순히 버퍼를 복사하는 것보다이 작업을 수행하는 데 더 많은 비용이 듭니다. 문자열 구현에 대해 "쓰기시 복사"구현이 중단 된 동일한 이유입니다.
따라서 .c_str()
진정으로 불변의 작업을 만드는 것이 가장 현명한 작업으로 판명되었지만 이제 스레드를 인식하는 표준에서 "신뢰"할 수 있습니까? 따라서 새로운 표준은 당신이 할 수 있다고 명확하게 명시하기로 결정했기 때문에 내부 표현은 null 종결자를 보유해야합니다.
잘 발견되었습니다. 이것은 확실히 최근 채택 된 표준의 결함입니다. 현재 사용중인 모든 코드를 깰 의도는 없었습니다 c_str
. 나는 결함 보고서를 제안하거나 적어도 comp.std.c++
(결함과 관련이있는 경우위원회에서 일반적으로 종료되는) 질문을 합니다.
참고 URL : https://stackoverflow.com/questions/7554039/is-stringc-str-no-longer-null-terminated-in-c11
'developer tip' 카테고리의 다른 글
문자열을 사용하여 동적으로 메서드를 호출하는 Objective C (0) | 2020.10.27 |
---|---|
Glimpse를 프로덕션 사이트에 배포해야합니까? (0) | 2020.10.27 |
Mac에서 bashrc 파일은 어디에서 찾을 수 있습니까? (0) | 2020.10.27 |
Java는 0 년이 윤년이지만 0 년은 존재하지 않았다고 말합니다. (0) | 2020.10.27 |
HTML에서 IMG의 높이 및 너비 속성을 지정해야합니까? (0) | 2020.10.27 |