문자열 c_str () 대 data () null로 종료되는 반면 data()그렇지 않은

c_str()data()(STL 및 기타 구현에서) 의 차이점 c_str()은 항상 null로 종료되는 반면 data()그렇지 않은 경우 여러 곳을 읽었습니다 . 내가 실제 구현에서 본 한, 그들은 동일하거나 data()호출합니다 c_str().

내가 여기서 무엇을 놓치고 있습니까? 어떤 시나리오에서 사용하는 것이 더 정확합니까?



답변

문서가 정확합니다. 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 유형의 객체에 대한 참조가 수정되지 않습니다.


답변

.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 종결자가 필요하지 않습니다. string0으로 끝나는 문자열을 예상하는 함수에을 전달하지 않는 한 생략 할 수 있습니다.

이를 통해 구현에서 하위 문자열이 실제 문자열 데이터 string::substr를 공유 할 수 있습니다. 내부적으로 공유 문자열 데이터에 대한 참조와 시작 / 종료 범위를 보유 할 수 있으므로 실제 문자열 데이터 의 복사 (및 추가 할당)를 피할 수 있습니다. 구현은 c_str을 호출하거나 문자열을 수정할 때까지 복사를 연기합니다. 관련된 strigns를 읽은 경우에는 사본이 만들어지지 않습니다.

(기록 중 복사 구현은 다중 스레드 환경에서 그다지 재미가 없으며, 일반적인 메모리 / 할당 절약은 오늘날 더 복잡한 코드의 가치가 없으므로 거의 수행되지 않습니다).


마찬가지로 string::data로프 (문자열 세그먼트의 링크 된 목록)와 같은 다른 내부 표현을 허용합니다. 이는 삽입 / 교체 작업을 크게 향상시킬 수 있습니다. 다시, 세그먼트의 목록은 호출 할 때 하나의 세그먼트에 붕괴되어야 할 것이다 c_strdata.


답변

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.

답변

이전의 모든 주석은 일관성이지만 C ++ 17부터 str.data ()가 const char * 대신 char *를 반환한다는 것을 추가하고 싶습니다.


답변