UFO ET IT

많은 프로그래밍 언어에서 문자열을 변경할 수없는 이유는 무엇입니까?

ufoet 2020. 12. 12. 11:53
반응형

많은 프로그래밍 언어에서 문자열을 변경할 수없는 이유는 무엇입니까?


중복 가능성 :
Java 및 .NET에서 문자열을 변경할 수없는 이유는 무엇입니까?
.NET String이 변경 불가능한 이유는 무엇입니까?

이를 위해 C #, Java 및 Python과 같은 여러 언어가 선택되었습니다. 메모리를 절약하거나 compare 와 같은 작업의 효율성을 높이려는 경우 연결 및 기타 수정 작업에 어떤 영향을 미칩니 까?


불변 유형은 일반적으로 좋은 것입니다.

  • 동시성에 대해 더 잘 작동합니다 (변경할 수없는 것을 잠글 필요가 없습니다!).
  • 오류를 줄입니다. 변경 가능한 객체는 모든 종류의 이상한 버그를 유발할 수있는 것으로 예상하지 않을 때 변경되기에 취약합니다 ( "원거리에서의 작업").
  • 메모리 소비를 줄이고 캐시 활용도를 향상시킬 수있는 안전하게 공유 될 수 있습니다 (즉, 동일한 객체에 대한 여러 참조).
  • 공유는 또한 변경 가능한 객체의 방어적인 복사본을 가져와야하는 경우 O (n) 일 때 복사하는 것이 매우 저렴한 O (1) 작업을 만듭니다. 복사는 매우 일반적인 작업이기 때문에 이것은 큰 문제입니다 (예 : 매개 변수를 전달할 때마다 ....).

결과적으로 문자열을 변경 불가능하게 만드는 것은 상당히 합리적인 언어 디자인 선택입니다.

일부 언어 (특히 Haskell 및 Clojure와 같은 기능적 언어)는 훨씬 더 나아가 거의 모든 것을 불변으로 만듭니다. 불변성의 이점에 관심이 있다면 계몽적인 동영상을 볼 가치가 있습니다.

불변 유형에는 몇 가지 사소한 단점이 있습니다.

  • 연결과 같이 변경된 문자열을 만드는 작업은 새 개체를 생성해야하므로 비용이 더 많이 듭니다. Rope 와 같은 트리 기반 문자열 데이터 구조를 사용하는 경우 O (log (m + n))만큼 낮을 수 있지만 일반적으로 두 개의 불변 문자열을 연결하는 데 드는 비용은 O (n + m)입니다 . 또한 문자열을 효율적으로 연결해야하는 경우 항상 Java의 StringBuilder 와 같은 특수 도구를 사용할 수 있습니다 .
  • 큰 문자열을 조금만 변경하면 큰 문자열의 완전히 새로운 복사본을 생성해야 할 수 있으며, 이는 분명히 메모리 소비를 증가시킵니다. 그러나 이것은 일반적으로 가비지 수집 언어에서 큰 문제가 아닙니다. 참조를 유지하지 않으면 오래된 복사본이 꽤 빨리 가비지 수집되기 때문입니다.

전반적으로 불변성의 장점은 사소한 단점보다 훨씬 큽니다. 성능에만 관심이 있더라도 복사의 동시성 이점과 저렴함은 일반적으로 잠금 및 방어 복사를 사용하는 변경 가능한 문자열보다 변경 불가능한 문자열을 훨씬 더 성능있게 만듭니다.


주로 프로그래밍 오류를 방지하기위한 것입니다. 예를 들어 문자열은 해시 테이블에서 키로 자주 사용됩니다. 변경 될 수 있으면 해시 테이블이 손상됩니다. 그리고 그것은 사용하는 동안 데이터의 일부가 변경되면 문제가 발생하는 한 가지 예일뿐입니다. 보안은 또 다른 문제입니다. 사용자가 요청한 작업을 실행하기 전에 지정된 경로에서 파일에 액세스 할 수 있는지 여부를 확인하는 경우 경로가 포함 된 문자열은 변경되지 않는 것이 좋습니다.

멀티 스레딩을 할 때 더욱 중요해집니다. 변경 불가능한 데이터는 스레드간에 안전하게 전달 될 수 있으며 변경 가능한 데이터는 끝없는 골칫거리를 유발합니다.

기본적으로 변경 불가능한 데이터는 작동하는 코드를 추론하기 쉽게 만듭니다. 이것이 순전히 기능적인 언어가 모든 것을 불변 으로 유지하려는 이유 입니다.


Java에서는 String뿐만 아니라 모든 기본 래퍼 클래스 (Integer, Double, Character 등)는 변경할 수 없습니다. 정확한 이유는 확실하지 않지만 모든 프로그래밍 체계가 작동하는 기본 데이터 유형이라고 생각합니다. 그들이 변하면 상황이 거칠어 질 수 있습니다. 보다 구체적으로 예를 들어 보겠습니다. 원격 호스트에 대한 소켓 연결을 열었다 고 가정합니다. 호스트 이름은 문자열이고 포트는 정수입니다. 연결이 설정된 후 이러한 값이 수정되면 어떻게됩니까?

성능에 관한 한 Java는 스택이나 힙이 아닌 리터럴 풀이라는 별도의 메모리 섹션에서 이러한 클래스에 메모리를 할당합니다. 리터럴 풀은 인덱싱되며 "String"문자열을 두 번 사용하면 리터럴 풀에서 동일한 개체를 가리 킵니다.


문자열을 불변으로 사용하면 이전에 만든 문자열 풀에서 동일 / 유사한 문자열을 쉽게 사용할 수 있으므로 새로운 문자열 참조를 쉽게 할 수 있습니다. 따라서 새로운 개체 생성 비용이 절감됩니다.

참고 URL : https://stackoverflow.com/questions/9544182/why-are-strings-immutable-in-many-programming-languages

반응형