답변:
문서가 정확합니다. c_str()
널로 끝나는 문자열을 원하는 경우 사용하십시오 .
구현자가 당신의 data()
관점 에서 구현 한 경우 c_str()
걱정할 data()
필요가 없습니다. 문자열이 null로 종료 될 필요가 없다면 여전히 사용 하십시오. 일부 구현에서는 c_str ()보다 더 나은 성능을 보일 수 있습니다.
문자열은 반드시 문자 데이터로 구성 될 필요는 없으며 모든 유형의 요소로 구성 될 수 있습니다. 이 경우 data()
더 의미가 있습니다. c_str()
제 생각에는 문자열의 요소가 문자 기반 일 때만 정말 유용합니다.
Extra : C ++ 11부터는 두 함수가 동일해야합니다. 즉, data
이제 null로 끝나야합니다. cppreference 에 따르면 : "반환 된 배열은 null로 종료됩니다. 즉, data () 및 c_str ()은 동일한 기능을 수행합니다."
에서 C ++ 11 / C ++ 0X , data()
그리고 c_str()
더 이상 다릅니다. 따라서 data()
끝에도 null 종료가 필요합니다.
21.4.7.1
basic_string
접근 자 [string.accessors]
const charT* c_str() const noexcept;
const charT* data() const noexcept;
1 개 반환 값 : 포인터 p를되도록
p + i == &operator[](i)
각i
에서[0,size()]
.
21.4.5 basic_string 요소 액세스 [string.access]
const_reference operator[](size_type pos) const noexcept;
1 필요 : pos <= size (). 2 반환 값 :
*(begin() + pos) if pos < size()
, 그렇지 않으면charT();
참조 된 값이 있는 값을 가진 T 유형의 객체에 대한 참조가 수정되지 않습니다.
std::string
추가 할당 char
후행 대한 '\0'
. 그렇게하면 및 std::string s("\0");
둘 다 0으로 평가됩니다.s.data()[0]
s.data()[1]
.data ()가 .c_str ()을 호출한다는 것을 알고 있더라도 이것이 다른 컴파일러의 경우라고 가정하는 것은 옳지 않습니다. 컴파일러가 향후 릴리스에서 변경 될 수도 있습니다.
std :: string을 사용하는 2 가지 이유 :
std :: string은 텍스트 및 임의의 이진 데이터 모두에 사용할 수 있습니다.
//Example 1
//Plain text:
std::string s1;
s1 = "abc";
//Example 2
//Arbitrary binary data:
std::string s2;
s2.append("a\0b\0b\0", 6);
예제 1과 같이 문자열을 사용할 때는 .c_str () 메서드를 사용해야합니다.
예제 2와 같이 문자열을 사용할 때는 .data () 메서드를 사용해야합니다. 이러한 경우 .c_str ()을 사용하는 것이 위험하기 때문이 아니라 다른 사람이 검토 할 수 있도록 바이너리 데이터로 작업하는 것이 더 명확하기 때문입니다. 귀하의 코드.
.data () 사용시 가능한 함정
다음 코드는 잘못되었으며 프로그램에서 segfault를 일으킬 수 있습니다.
std::string s;
s = "abc";
char sz[512];
strcpy(sz, s.data());//This could crash depending on the implementation of .data()
구현자가 .data ()와 .c_str ()이 같은 일을하도록 만드는 것이 일반적인 이유는 무엇입니까?
그렇게하는 것이 더 효율적이기 때문입니다. .data ()가 null로 끝나지 않은 것을 반환하도록하는 유일한 방법은 .c_str () 또는 .data ()가 내부 버퍼를 복사하도록하거나 2 개의 버퍼를 사용하는 것입니다. null로 끝나는 단일 버퍼가 있다는 것은 std :: string을 구현할 때 항상 내부 버퍼를 하나만 사용할 수 있음을 의미합니다.
이미 답변을 받았으며 목적에 대한 몇 가지 메모 : 구현의 자유.
std::string
작업 (예 : 반복, 연결 및 요소 변형)에는 0 종결자가 필요하지 않습니다. string
0으로 끝나는 문자열을 예상하는 함수에을 전달하지 않는 한 생략 할 수 있습니다.
이를 통해 구현에서 하위 문자열이 실제 문자열 데이터 string::substr
를 공유 할 수 있습니다. 내부적으로 공유 문자열 데이터에 대한 참조와 시작 / 종료 범위를 보유 할 수 있으므로 실제 문자열 데이터 의 복사 (및 추가 할당)를 피할 수 있습니다. 구현은 c_str을 호출하거나 문자열을 수정할 때까지 복사를 연기합니다. 관련된 strigns를 읽은 경우에는 사본이 만들어지지 않습니다.
(기록 중 복사 구현은 다중 스레드 환경에서 그다지 재미가 없으며, 일반적인 메모리 / 할당 절약은 오늘날 더 복잡한 코드의 가치가 없으므로 거의 수행되지 않습니다).
마찬가지로 string::data
로프 (문자열 세그먼트의 링크 된 목록)와 같은 다른 내부 표현을 허용합니다. 이는 삽입 / 교체 작업을 크게 향상시킬 수 있습니다. 다시, 세그먼트의 목록은 호출 할 때 하나의 세그먼트에 붕괴되어야 할 것이다 c_str
나 data
.
ANSI ISO IEC 14882 2003
(C ++ 03 표준) 에서 인용 :
21.3.6 basic_string string operations [lib.string.ops]
const charT* c_str() const;
Returns: A pointer to the initial element of an array of length size() + 1 whose first size() elements
equal the corresponding elements of the string controlled by *this and whose last element is a
null character specified by charT().
Requires: The program shall not alter any of the values stored in the array. Nor shall the program treat the
returned value as a valid pointer value after any subsequent call to a non-const member function of the
class basic_string that designates the same object as this.
const charT* data() const;
Returns: If size() is nonzero, the member returns a pointer to the initial element of an array whose first
size() elements equal the corresponding elements of the string controlled by *this. If size() is
zero, the member returns a non-null pointer that is copyable and can have zero added to it.
Requires: The program shall not alter any of the values stored in the character array. Nor shall the program
treat the returned value as a valid pointer value after any subsequent call to a non- const member
function of basic_string that designates the same object as this.
.data()
대한 상수가 아닌 오버로드가 있으므로 상수가 아닌 문자열에 대해 더 이상 동일하지 않습니다.