std :: string 앞에 왜 많은 문자열 클래스가 있습니까?


56

많은 더 큰 C ++ 라이브러리가 결국 자체 문자열 유형을 만드는 것으로 보입니다. 클라이언트 코드에서는 (라이브러리에서 하나를 사용해야 하나 QString, CString, fbstring또는 대부분의 시간이 포함 된 (표준 타입과 일 사이에서 라이브러리 사용을 변환 유지, 나는 사람이 몇 이름을 지정할 수 있습니다 확신 등) 적어도 하나의 사본).

그렇다면 의미론이 나쁜 std::string것처럼 특정 기능이나 잘못된 점이 auto_ptr있습니까? C ++ 11에서 변경 되었습니까?


32
그것은 "여기서 발명하지 않았습니다"증후군이라고합니다.
Cat Plus Plus

10
@CatPlusPlus QString 및 CString은 모두 std :: string보다 우선합니다.
로봇 고트

8
@Cat Plus Plus :이 증후군은 Java String 클래스에 영향을 미치지 않는 것 같습니다.
Giorgio

20
@Giorgio : Java 프로그래머는 언어 부족으로 인해 문자열 클래스 (Android에서 String을 다시 만들었 음)에 대해 걱정할 수있는 해결 방법을 발명하기에 너무 바쁩니다.
고양이 플러스 플러스

9
@Giorgio : Java의 하드 코딩 된 구문 지원 java.lang.String(오퍼레이터 오버로드 부족 등)으로 인해 다른 것을 사용하기가 어려울 수 있습니다.
기계 달팽이

답변:


57

더 큰 C ++ 라이브러리의 대부분 std::string은 표준화 되기 전에 시작 되었습니다. 다른 기능으로는 UTF-8 지원 및 인코딩 간 변환과 같이 늦게 표준화되었거나 아직 표준화되지 않은 추가 기능이 있습니다.

이러한 라이브러리가 오늘날 구현 된 std::string경우 인스턴스에서 작동하는 함수 및 반복자를 작성하도록 선택했을 것입니다 .


5
UTF-8 지원은 C ++ 98부터 표준화되었습니다. 그러한 불편하고 부분적으로 구현 된 방법으로 아무도 그것을 사용할 수없는 것처럼 보입니다.
AProgrammer

9
@AProgrammer : charUTF-8 코드 포인트를 보유 할 수있을만큼 커야합니다. AFAIK는 C ++ 98이 제공 한 유일한 "지원"입니다.
Ben Voigt

4
@AProgrammer : 그 지원은 정말 쓸모가 없습니다.
DeadMG

4
@AProgrammer 로케일은 모든 유니 코드 코드 포인트를 표현하기에 충분히 크지 않기 때문에 논란의 여지 wchar_t가 있습니다. 더욱이 UTF-16 에 대한이 모든 논의는 UTF -8이 독점적으로 사용되어야 한다는 매우 강력한 주장이 이루어진 곳에서 유해한 것으로 간주 되었습니다 .
Konrad Rudolph

6
@KonradRudolph, 그것은 로케일 시스템이 아닙니다. wchar_t의 정의는 "지원되는 문자 세트에 대해 충분히 넓습니다"; wchar_t가 16 비트를 커밋 한 시스템은 동시에 유니 코드를 지원하지 않습니다. 범인은 유니 코드로, 16 비트 이상이 필요한 코드 포인트를 사용하지 않고 16 비트 wchar_t에 커밋 한 시스템, 16 비트 이상이 필요한 유니 코드 전환을 절대 사용하지 않도록 보장합니다.
AProgrammer

39

문자열은 C ++의 큰 부끄러운 일입니다.

처음 15 년 동안 모든 플랫폼의 모든 컴파일러와 모든 사용자가 고유 한 클래스를 작성하도록하는 문자열 클래스를 전혀 제공하지 않습니다.

그런 다음 전체 문자열 조작 API인지 아니면 STL char 컨테이너인지에 대해 혼란스러워하는 것을 만듭니다. 일부 알고리즘은 std :: Vector에 복제하거나 다른 알고리즘이 있습니다.

replace () 또는 mid ()와 같은 명백한 문자열 연산이 반복자의 혼란으로 인해 단일 '페이지에 문장을 유지하기 위해 새로운'자동 '키워드를 도입해야하며 대부분의 사람들이 전체 언어를 포기하게합니다. .

그런 다음 유니 코드 'support'와 std :: wstring은 arghh입니다 .....

감사합니다-지금 기분이 나아지고 있습니다.


12
@DeadMG-예. 1998 년에 발명 된지 15 년이 지난 후, MSFT도 사용하고 6 년이 지난 후에 표준화되었습니다. 예 반복자는 배열과 목록을 동일하게 만드는 유용한 방법입니다. 문자열 조작을 수행하는 명백한 방법이라고 생각하십니까?
Martin Beckett

3
클래스가있는 C는 1983 년에 발명되었습니다. C ++이 아닙니다. 유일한 표준 라이브러리는 그 표준 -에 의해 결정되는, 이상하게위한 가장 빠른 날짜 있도록, 표준을 일단에만 일어날 수 있는 표준 라이브러리가 1998 년이며, 반복자는 인덱스와 정확하게 동일한 것으로 간주 할 수 있지만, 강력한 형식. 나는 반복자가 범위와 비교할 때 빨라진다는 사실에 관한 것이지만 실제로는 특정하지 않습니다 std::string. 1983 년에 String 클래스가 없다고해서 더 많은 것을 가지고 있다고해서 정당화되는 것은 아닙니다.
DeadMG

8
나는 iostream이 C ++의 큰 당황이라고 생각했습니다 ...
Doug T.

18
@DeadMG 사람들은 1998 년 이전에 몇 년 동안 "C ++"라는 것을 사용하고있었습니다. 저는 1985 년 "C ++"라는 것을 사용하여 첫 번째 프로그램을 작성했습니다. 이 전에 코드를 작성하고 어딘가에서 문자열 클래스를 가져와야했습니다. 우리가 이러한 레거시 코드베이스를 가지고 나면 표준을 얻었을 때 정확하게 폐기하거나 처음부터 다시 작성할 수 없었습니다. 이제 어떻게 해야 일어난 것은 cfront와 함께 문자열 클래스가 있었어야한다는 것입니다.
로봇 고트

8
@DeadMG-ISO 인증을 받기 전까지는 아무도 언어를 사용하지 않으면 ISO에 도달하지 않으므로 사용 된 언어가 없습니다. x86 어셈블러에 대한 ISO 표준은 없지만 플랫폼을 사용하게되어 기쁩니다
Martin Beckett

32

실제로 ...에는 몇 가지 문제가 std::string있으며 C ++ 11에서는 조금 나아지지만 앞서 나가지 마십시오.

QString그리고 오래된 라이브러리의 CString일부 이므로 C ++이 표준화되기 전에 존재했습니다 (SGI STL과 유사). 그들은 이렇게 했다 클래스를 만들 수 있습니다.

fbstring매우 구체적인 성능 문제를 해결합니다. 표준은 인터페이스를 규정하고 알고리즘 복잡도는 최소를 보장하지만 이것이 빠른지 아닌지에 대한 구현 품질 세부 사항입니다. fbstring특정 최적화 (예 : 스토리지 관련 또는 더 빠름 find)가 있습니다.

여기서 제기되지 않은 다른 관심사 (en vrac) :

  • C ++ 03에서는 스토리지가 연속적이어야하므로 C와의 상호 운용성이 잠재적으로 어려워집니다. C ++ 11에서이 문제를 해결했습니다.
  • std::string 인식하지 못하고 UTF-8에 대한 특수 코드가 없으므로 UTF-8 문자열을 쉽게 저장하고 실수로 손상시킬 수 있습니다
  • std::string인터페이스가 부풀어지고 많은 메소드가 자유 함수로 구현되었을 수 있으며 많은 메소드가 인덱스 기반 인터페이스 및 반복자 기반 인터페이스를 준수하도록 복제되었습니다.

5
우려 사항 # 1-C ++ 03 21.3.6 / 1은 c_str()인접한 스토리지에 대한 포인터를 반환하여 일부 C 상호 운용성을 제공합니다. 그러나 지정된 데이터는 수정할 수 없습니다. 일반적인 해결 방법에는 vector<char>.
존 디 블링

@JohnDibling : 예. 또 다른 제한이 있습니다. 새로 할당 된 스토리지에 사본이 발생할 수 있습니다 (표준에서는 그렇지 않다고 말하지 않습니다). 물론 C ++ 11도 복사를 막을 수 &s[0]는 없지만 더 이상 중요하지 않습니다. :)
Matthieu M.

1
@MatthieuM .: via를 통해 얻은 포인터 &s[0]는 NUL로 끝나는 문자열을 가리킬 수 없습니다 ( c_str()마지막 수정 이후에 호출 되지 않은 경우 ).
벤 Voigt

2
@Matthieu : 다른 버퍼는 허용되지 않습니다. " c_str()반환 값 : 포인터 p등 그 p + i == &operator[](i)각각 i[0,size()]".
Ben Voigt 2016 년

3
주목할만한 점은 더 이상 올바른 마음을 가진 사람이 더 이상 MFC를 사용하지 않으므로 CString이 현대 C ++의 문자열 클래스라고 주장하기가 어렵습니다.
DeadMG

7

여기에 게시 된 이유 외에도 다른 이진 호환성도 있습니다. 라이브러리 작성자 std::string는 사용 중인 구현과 동일한 메모리 레이아웃을 갖는지 여부를 제어 할 수 없습니다 .

std::string는 템플릿이므로 구현은 로컬 STL 헤더에서 가져옵니다. 이제 표준과 완전히 호환되는 일부 성능 최적화 STL 버전을 로컬에서 사용한다고 가정 해보십시오. 예를 들어, std::string동적 할당 및 캐시 누락 수를 줄이기 위해 각각 정적 버퍼를 도입하도록 선택했을 수 있습니다 . 결과적으로 구현의 메모리 레이아웃 및 / 또는 크기는 라이브러리와 다릅니다.

레이아웃 만 다른 경우 std::string라이브러리에서 클라이언트로 전달 된 인스턴스 또는 다른 방식으로 전달 된 인스턴스 에서 일부 멤버 함수 호출은 실패한 멤버에 따라 실패 할 수 있습니다.

크기도 다르면 std::string멤버 및 라이브러리가 클라이언트 라이브러리에서 체크인 될 때 ​​멤버가있는 모든 라이브러리 유형의 크기가 다른 것으로 나타납니다. 멤버 다음에 오는 데이터 멤버 std::string도 오프셋이 이동하며 라이브러리 자체를 디버깅 할 때 "확인"으로 표시되지만 클라이언트에서 호출 된 모든 직접 액세스 / 인라인 접근자는 쓰레기를 반환합니다.

결론-라이브러리와 클라이언트 코드가 다른 std::string버전으로 다시 컴파일 되면 제대로 링크되지만 버그를 이해하기가 어려울 수 있습니다. std::string구현 을 변경하면 STL에서 멤버를 노출시키는 모든 라이브러리를 클라이언트의 std::string레이아웃 과 일치하도록 다시 컴파일해야 합니다. 또한 프로그래머는 라이브러리가 견고하기를 원하기 때문에 거의 std::string어디에도 노출 되지 않습니다 .

공평하게 말하면, 이것은 모든 STL 유형에 적용됩니다. IIRC에는 표준화 된 메모리 레이아웃이 없습니다.


2
* nix 프로그래머 여야합니다. C ++ 이진 호환성은 모든 플랫폼에서 동일하지 않으며, 특히 Windows에서 데이터 멤버를 포함하는 NO 클래스는 컴파일러간에 이식 가능하지 않습니다.
Ben Voigt 2016

(POD 유형을 제외하고는 명시적인 포장 요구 사항이 필요함)
Ben Voigt

1
입력에 감사드립니다. 다른 컴파일러를 말하는 것은 아니지만 다른 STL을 말하는 것입니다.
gwiazdorrr 2016 년

1
+1 : ABI는 컴파일러가 제공하는 클래스의 자체 버전을 롤업해야하는 큰 이유입니다. 그것만으로도 이것이 받아 들여지는 대답이기를 바랍니다.
Thomas Eding

6

질문에 대한 많은 답변이 있지만 여기에 몇 가지가 있습니다.

  1. 유산. std :: string이 존재하기 전에 많은 문자열 라이브러리와 클래스가 작성되었습니다.

  2. C의 코드와의 호환성을 위해 std :: string 라이브러리는 C ++이며 C 및 C ++에서 작동하는 다른 문자열 라이브러리가 있습니다.

  3. 동적 할당을 피하기 위해. 라이브러리 std :: string은 동적 할당을 사용하므로 임베디드 시스템, 인터럽트 또는 실시간 관련 코드 또는 저수준 기능에는 적합하지 않을 수 있습니다.

  4. 템플릿. 라이브러리 std :: string은 템플리트를 기반으로합니다. 상당히 최근까지 많은 C ++ 컴파일러는 성능이 좋지 않거나 버그가 많은 템플릿 지원을 제공했습니다. 불행히도, 저는 많은 커스텀 툴을 사용하는 업계에서 일하고 있으며 업계의 주요 업체의 툴체인 중 하나가 C ++을 "공식적으로"100 % 지원하지 않습니다 (버그 등이 템플릿 등).

아마도 더 많은 이유가있을 것입니다.


2
"최근에 최근에"라는 의미는 "Visual Studio조차도 꽤 합리적인 지원을 제공한지 10 년이 지났습니까?"
DeadMG

@DeadMG-Visual Studio는 세계에서 유일하게 비 호환 컴파일러가 아닙니다. 비디오 게임에서 일하고 있으며 출시되지 않은 하드웨어 플랫폼 (콘솔주기에서 또는 새로운 하드웨어가 나타날 때마다 몇 년마다 발생 함)에 대한 사용자 지정 컴파일러를 사용하는 경우가 많습니다. "최근에 최근에"는 오늘을 의미합니다. 현재 특정 컴파일러는 템플릿을 잘 지원하지 않습니다. NDA를 위반하지 않고 구체적으로 말할 수는 없지만 현재 C ++ 지원 (특히 템플릿 준수)이 "실험적인"것으로 간주되는 맞춤형 툴체인이있는 플랫폼에서 작업하고 있습니다.
Adisak

4

주로 유니 코드에 관한 것입니다. 유니 코드에 대한 표준 지원은 기껏해야 무방하며 모든 사람은 고유 한 유니 코드 요구가 있습니다. 예를 들어, ICU는 여러분이 상상할 수있는 가장 역겨운 자동 생성 Java 인터페이스 뒤에서 원하는 모든 유니 코드 기능을 지원하며, Unix를 사용하는 경우 UTF-16을 사용하고 있다면 좋은 시간.

또한 많은 사람들이 다른 수준의 유니 코드 지원을 필요로합니다. 모든 사람이 복잡한 텍스트 레이아웃 API 등을 필요로하는 것은 아닙니다. 따라서 수많은 문자열 클래스가 존재하는 이유를 쉽게 알 수 있습니다. 표준 클래스는 매우 짜증스럽고 모든 사람들이 새로운 클래스와는 다른 요구를 가지고 있으며 아무도 즐거운 인터페이스로 크로스 플랫폼을 통해 많은 유니 코드 지원을 수행 할 수있는 단일 클래스를 만들 수 없습니다.

제 생각에 이것은 1998 년 또는 2003 년에 유니 코드를 올바르게 지원하지 않은 C ++위원회의 잘못입니다. 아마도 C ++ 11에서는 이해할 수 없었습니다. 희망적으로 C ++ 17에서는 더 잘 할 것입니다.


안녕하세요, C ++ 20, 유니 코드 지원에 어떤 일이 일어 났습니까?
통행인

-4

모든 프로그래머가 증명할 무언가가 있고, 하나의 멋진 기능을 위해 자신 만의 멋진 문자열 클래스를 만들어야 할 필요가 있기 때문입니다. 일반적으로 약간 불필요하며 내 경험에 따라 모든 종류의 추가 문자열 변환이 발생합니다.


7
이것이 사실이라면 좋은 구현이 모두 가능한 Java와 같은 언어에서 비슷한 수의 String 구현을 기대할 수 있습니다.
Bill K

@BillK Java String은 최종적이므로 다른 곳에 새로운 기능을 추가해야합니다.

그리고 내 요점은 20 년 만에 최종 사용자가 사용자 정의 문자열 요소를 작성하는 것을 본 적이 없다는 것입니다.
Bill K

2
@Bill : 다른 문화와 관련이있을 수 있습니다. C ++은 저수준 세부 사항을 이해하려는 사람들을 끌어들입니다. Java는 다른 사람의 빌딩 블록을 사용하여 일을 끝내려는 사람들을 끌어들입니다. (이것은 어떤 언어를 사용하기로 선택한 특정 개인에 대한 진술이 아니라 언어의 각 디자인 목표와 문화에 대한 진술입니다)
Ben Voigt
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.