UFO ET IT

불변 문자열 대 std :: string

ufoet 2020. 12. 1. 20:09
반응형

불변 문자열 대 std :: string


최근에 불변 문자열에 대해 읽었 습니다. Java 및 .NET에서 문자열을 변경할 수없는 이유는 무엇입니까? 그리고 왜 .NET 문자열은 불변인가? D 가 불변의 문자열을 선택 했는지에 대한 몇 가지 사항도 있습니다. 많은 장점이있는 것 같습니다.

  • 사소한 스레드 안전
  • 더 안전한
  • 대부분의 사용 사례에서 더 많은 메모리 효율성.
  • 저렴한 부분 문자열 (토큰 화 및 슬라이스)

말할 것도없이 대부분의 새로운 언어에는 D2.0, Java, C #, Python 등 불변의 문자열이 있습니다.

C ++가 변경 불가능한 문자열의 이점을 얻을 수 있습니까?

이러한 모든 장점을 가진 C ++ (또는 C ++ 0x)에서 변경 불가능한 문자열 클래스를 구현할 수 있습니까?


최신 정보:

변경 불가능한 문자열 const_stringfix_str 에는 두 번의 시도가 있습니다 . 둘 다 5 년 동안 업데이트되지 않았습니다. 그들은 심지어 사용됩니까? const_string이 부스트되지 않은 이유는 무엇입니까?


의견으로 :

  • 예, 저는 C ++를위한 불변의 문자열 라이브러리를 원합니다.
  • 아니요, std :: string을 변경할 수 없도록하고 싶습니다.

(표준 라이브러리 기능으로) 정말 가치가 있습니까? 나는 말하지 않을 것이다. const를 사용하면 로컬에서 변경할 수없는 문자열이 제공되며 시스템 프로그래밍 언어의 기본 특성은 실제로 변경 가능한 문자열이 필요함을 의미합니다.


이 스레드의 대부분의 사람들이 실제로 무엇인지 이해하지 못하는 것을 발견했습니다 immutable_string. 그것은 단지 불변성에 관한 것이 아닙니다. 진정한 힘은 immutable_string성능 (단일 스레드 프로그램에서도)과 메모리 사용량입니다.

모든 문자열이 변경 불가능하고 모든 문자열이 다음과 같이 구현된다고 상상해보십시오.

class string {
    char* _head ;
    size_t _len ;
} ;

sub-str 연산을 어떻게 구현할 수 있습니까? 문자를 복사 할 필요가 없습니다. 우리가해야 할 일은 _head_len. 그런 다음 하위 문자열은 소스 문자열과 동일한 메모리 세그먼트를 공유합니다.

물론 두 개의 데이터 멤버만으로 immutable_string을 구현할 수는 없습니다. 실제 구현에는 참조 카운트 (또는 플라이 가중치) 메모리 블록이 필요할 수 있습니다. 이렇게

class immutable_string {
    boost::fly_weight<std::string> _s ;
    char* _head ;
    size_t _len ;
} ;

메모리와 성능 모두 대부분의 경우, 특히 수행중인 작업을 알고있는 경우 기존 문자열보다 더 좋습니다.

물론 C ++는 변경 불가능한 문자열의 이점을 얻을 수 있으며 하나가있는 것이 좋습니다. 나는 Cubbi boost::const_stringfix_str언급 한 것을 확인했습니다 . 내가 말하고있는 것이어야합니다.


내 결론은 C ++에는 const 의미가 있기 때문에 불변 패턴이 필요하지 않다는 것입니다.

Java에서 Person클래스 String name가 있고 getName()메소드로 사람 을 반환하는 경우 유일한 보호는 변경 불가능한 패턴입니다. 이것이 없으면 clone()밤낮으로 문자열 을 처리 해야합니다 (일반적인 값 개체는 아니지만 여전히 보호해야하는 데이터 멤버와 관련이 있음).

C ++에서는 const std::string& getName() const. 그래서 당신은 SomeFunction(person.getName())그것이 어디에 있는지 쓸 수 있습니다 void SomeFunction(const std::string& subject).

  • 사본이 발생하지 않았습니다.
  • 누구든지 복사하고 싶다면 그렇게 할 수 있습니다.
  • 기술은 문자열뿐만 아니라 모든 데이터 유형에 적용됩니다.

그래도 당신은 확실히 유일한 사람이 아닙니다. 사실, Maxim Yegorushkin의 const_string 라이브러리가 있는데, 이는 부스트를 염두에두고 작성된 것으로 보입니다. 여기 Roland Pibinger의 fix_str 라이브러리가 있습니다. 런타임에 풀 스트링 인턴이 얼마나 까다로운 지 잘 모르겠지만 필요한 경우 대부분의 이점을 얻을 수 있습니다.


여기에 확실한 답은 없다고 생각합니다. 그것은 주관적입니다. 개인적인 취향 때문이 아니라면 적어도 가장 자주 다루는 코드 유형 때문입니다. (그래도 귀중한 질문입니다.)

변경 불가능한 문자열은 메모리가 저렴할 때 유용합니다. 이것은 C ++가 개발되었을 때는 사실이 아니었고 C ++가 대상으로하는 모든 플랫폼에서 그런 것도 아닙니다. (더 제한된 플랫폼 C의 OTOH는 C ++보다 훨씬 더 일반적으로 보이므로 인수가 약합니다.)

C ++에서 변경 불가능한 문자열 클래스를 생성 할 수 있으며 대부분과 호환되도록 만들 수 있습니다. std::string그러나 전용 최적화 및 언어 기능이있는 내장 문자열 클래스와 비교할 때 여전히 손실됩니다.

std::string우리가 얻는 최고의 표준 문자열이므로 엉망이되는 것을보고 싶지 않습니다. 그래도 아주 드물게 사용합니다. 내 관점에서std::string 너무 많은 단점 이 있습니다 .


const std::string

됐습니다. 정의되지 않은 동작을 원하지 않는 한 문자열 리터럴도 변경할 수 없습니다.

편집 : 물론 그것은 이야기의 절반에 불과합니다. const 문자열 변수는 새 문자열을 참조하도록 만들 수 없기 때문에 유용하지 않습니다. const 문자열에 대한 참조는이를 수행합니다. 단, C ++에서는 Python과 같은 다른 언어 에서처럼 참조를 다시 할당 할 수 없습니다. 가장 가까운 것은 동적으로 할당 된 문자열에 대한 스마트 포인터입니다.


불변의 문자열은 훌륭 경우 는 새로운 문자열을 생성하는 것이 필요 할 때마다, 메모리 관리자는 항상 모든 문자열 참조의 행방을 결정 판단 할 수있을 것입니다. 대부분의 플랫폼에서 이러한 기능에 대한 언어 지원은 비교적 저렴한 비용으로 제공 될 수 있지만 그러한 언어 지원이 내장되지 않은 플랫폼에서는 훨씬 더 어렵습니다.

If, for example, one wanted to design a Pascal implementation on x86 that supported immutable strings, it would be necessary for the string allocator to be able to walk the stack to find all string references; the only execution-time cost of that would be requiring a consistent function-call approach [e.g. not using tail calls, and having every non-leaf function maintain a frame pointer]. Each memory area allocated with new would need to have a bit to indicate whether it contained any strings and those that do contain strings would need to have an index to a memory-layout descriptor, but those costs would be pretty slight.

If a GC wasn't table to walk the stack, then it would be necessary to have code use handles rather than pointers, and have code create string handles when local variables come into scope, and destroy the handles when they go out of scope. Much greater overhead.


Qt also uses immutable strings with copy-on-write.
There is some debate about how much performance it really buys you with decent compilers.


constant strings make little sense with value semantics, and sharing isn't one of C++'s greatest strengths...


Strings are mutable in Ruby.

$ irb
>> foo="hello"
=> "hello"
>> bar=foo
=> "hello"
>> foo << "world"
=> "helloworld"
>> print bar
helloworld=> nil
  • trivially thread safe

I would tend to forget safety arguments. If you want to be thread-safe, lock it, or don't touch it. C++ is not a convenient language, have your own conventions.

  • more secure

No. As soon as you have pointer arithmetics and unprotected access to the address space, forget about being secure. Safer against innocently bad coding, yes.

  • more memory efficient in most use cases.

Unless you implement CPU-intensive mechanisms, I don't see how.

  • cheap substrings (tokenizing and slicing)

That would be one very good point. Could be done by referring to a string with backreferences, where modifications to a string would cause a copy. Tokenizing and slicing become free, mutations become expensive.


C++ strings are thread safe, all immutable objects are guaranteed to be thread safe but Java's StringBuffer is mutable like C++ string is and the both of them are thread safe. Why worry about speed, define your method or function parameters with the const keyword to tell the compiler the string will be immutable in that scope. Also if string object is immutable on demand, waiting when you absolutely need to use the string, in other words, when you append other strings to the main string, you have a list of strings until you actually need the whole string then they are joined together at that point.

immutable and mutable object operate at the same speed to my knowledge , except their methods which is a matter of pro and cons. constant primitives and variable primitives move at different speeds because at the machine level, variables are assigned to a register or a memory space which require a few binary operations, while constants are labels that don't require any of those and are thus faster (or less work is done). works only for primitives and not for object.

참고URL : https://stackoverflow.com/questions/2916358/immutable-strings-vs-stdstring

반응형