2016-08-05 4 views
-6

문자열을 변경할 수 없다는 것을 알았습니다. 일단 변경할 수 없으면 새 문자열 객체를 만들고 값을 할당 한 다음 동일한 문자열 객체에 다른 값을 내부적으로 할당하면 실제로 읽을 수 있습니다. 새로운 값으로 생성되고 할당 된 객체. 의 내가 있다고 가정 해 봅시다 :문자열은 C#에서 어떻게 작동합니까?

string str = "dog";    
str = "cat"; 

을 나는 그것이 cat을 반환 Console.WriteLine(str);을 작성하는 경우. 내부적으로 두 개의 객체가 있습니까? 그러나 그들은 같은 이름을 가지고 있습니까? 어떻게 작동합니까? 나는 Google에 대한 조사를했지만 아직 내게 충분히 설득력있는 것을 찾지 못해서 내 생각을 분명히 할 수있다. 문자열이 참조 유형이라는 것을 알고 있으므로 힙의 값에 대한 참조와 함께 스택에 객체가 있습니다.이 경우 어떻게됩니까? (위의 코드 참조).

사진을 업로드했습니다.이 질문을하는 이유 인 스택 및 힙에 대한 아이디어가 잘못되어 사과드립니다. 첫 번째 코드 줄 (string str = "dog";)에서 어떤 현상이 나타나나요? 그리고 두 번째 코드 줄에서 어떻게되어야합니까 ?? 힙의 dog 값이 변경됩니까? 그런 다음 스택의 새 객체가 참조로 만들어집니다. 그렇다면 전에 있었던 물건은 어떻게 될까요? 그들은 같은 이름을 가지고 있습니까? 많은 질문에 대해 유감이지만이 문제를 제대로 이해하고 무엇이 일어나고 있는지 알기 위해서는 매우 중요하다고 생각합니다. enter image description here

답변

2

리뷰 String Interning 또는 .Net String Intern table 또는 CLR Intern Pool.
기본적으로 CLR (공용 언어 런타임)은 [고유 한] 문자열 값의 테이블을 유지 관리하며 코드에서 문자열을 조작 할 때마다 CLR은이 인턴 테이블을 검사하여 사용자가 작성하려는 새 값이 이미 존재하는지 확인합니다 거기 또는 아닙니다. 그럴 경우 수정중인 변수를 인턴 풀의 해당 항목을 가리 키도록 다시 지정합니다. 그렇지 않은 경우 풀에 값을 추가하고 해당 새 참조를 반환합니다. 변수에서 더 이상 참조하지 않는 풀의 이전 값은 가비지 수집됩니다.

+0

귀하의 모든 답변이 매우 설명하기 쉽기 때문에 대답을 선택하기가 매우 어려워서 고맙습니다. 감사합니다. – AlexGH

1

예, 두 가지 개체가 있습니다. 아니요, 그들은 같은 이름이 아닙니다. 변수를 객체 자체의 "이름"으로 생각하지 않으려 고 시도하십시오. 그 자체는입니다. 이것은 메모리에있는 객체의 위치에 대한 임시 이름과 더 비슷합니다. (변수를 객체의 "이름"으로 생각하는 것이 오해의 소지가있는 이유는 동일한 객체를 참조하는 변수가 여러 개있을 수 있기 때문이며 객체 자체에 여러 "이름"이 있거나 객체가 여러 개있는 경우가 아닙니다 여러 객체가 있습니다. 참조를 저장하는 방법입니다.

"string str"은 처음에는 "dog"문자열을 참조합니다. "cat"을 "str"에 할당하면 이제 변수에 문자열 "cat"에 대한 참조가 있습니다.

두 문자열이 여전히 메모리에 남아 있지만 (적어도 일시적으로) "dog"문자열은 더 이상 참조 할 수 없기 때문에 더 이상 액세스 할 수 없으므로 더 이상 액세스 할 수 없습니다. 가비지 컬렉터가 더 이상 아무런 참조가 없기 때문에 메모리에서 "개"문자열을 삭제할 수 있기 때문에 둘 다 메모리에 존재하는 지 미리 알 수 없습니다.

그런데 힙에있는 객체에 대한 참조가있는 스택에 대한 값은 정확합니다. 좋은 구분입니다.

2

끝났습니다. 사진은 코드의 첫 번째 줄에서 일어나는 일을 정확하게 나타냅니다. 그러나 두 번째 코드 줄에서 설명하는 것과는 조금 다릅니다.

라인의 경우 str = "cat";의 경우 두 번째 문자열 객체가 힙에 만들어지고 str 변수가 새 객체를 참조하도록 변경됩니다. str"cat"을 가리키며 힙에는 "dog"의 고아 개체가 참조되어 있지 않습니다.

"dog" 개체는 참조가 없으므로 가비지 수집기에서 정리할 수 있습니다.

4

"dog"에 str을 할당하면 위에서 설명한대로 수행됩니다. 참조 변수 str은 방금 인스턴스화 한 문자열의 위치를 ​​"가리키고 있습니다". str이 새로운 문자열, "고양이"에 재 할당됩니다

str => MEMORY LOCATION "1": "dog" 
     MEMORY LOCATION "2": 
     MEMORY LOCATION "3": 

, 그것은 너무 메모리에 생성되고,이 새로운 위치에 "고양이"에 가리 키도록 지금 str가 조정됩니다.

 MEMORY LOCATION "1": "dog" 
str => MEMORY LOCATION "2": "cat" 
     MEMORY LOCATION "3": 

"개"는 어떻게됩니까? 이제는 위치에 대한 참조가 더 이상 없으므로 (메모리, 힙, 용어는이 상황에서 상호 교환 가능) 효과적으로 액세스 할 수 없습니다. 나중에 가비지 수집기가 정리를 위해 메모리를 검토하면 "개"를 참조하는 것이 없으며 필요에 따라 삭제되고 교체되는 메모리를 표시합니다.