program tip

C # 참조와 포인터의 차이점은 무엇입니까?

radiobox 2020. 10. 9. 10:41
반응형

C # 참조와 포인터의 차이점은 무엇입니까?


C # 참조와 포인터의 차이점을 잘 이해하지 못합니다. 둘 다 기억 속의 장소를 가리 킵니다. 그렇죠? 내가 알아낼 수있는 유일한 차이점은 포인터가 똑똑하지 않고 힙의 어떤 것도 가리킬 수없고 가비지 수집에서 제외되며 구조체 또는 기본 유형 만 참조 할 수 있다는 것입니다.

내가 묻는 이유 중 하나는 사람들이 좋은 프로그래머가되기 위해 포인터를 잘 이해해야한다는 인식이 있다는 것입니다. 더 높은 수준의 언어를 배우는 많은 사람들은 이것을 놓치고 따라서 이러한 약점을 가지고 있습니다.

포인터에 대해 그렇게 복잡한 것을 이해하지 못합니까? 그것은 기본적으로 기억의 장소에 대한 참조 일 뿐이지 않습니까? 위치를 반환하고 해당 위치의 개체와 직접 상호 작용할 수 있습니까?

중요한 포인트를 놓친 적이 있습니까?


C # 참조는 가비지 수집기에 의해 재배치 될 수 있으며 재배치되지만 일반 포인터는 정적입니다. 이것이 우리 fixed가 배열 요소에 대한 포인터를 획득 할 때 키워드 를 사용 하여 이동을 방지하는 이유입니다.

편집 : 개념적으로, 예. 그들은 다소 동일합니다.


포인터와 참조 사이에는 약간의 차이가 있지만 매우 중요한 차이가 있습니다. 포인터는 메모리의 한 위치를 가리키고 참조는 메모리의 개체를 가리 킵니다. 포인터가 가리키는 메모리의 정확성을 보장 할 수 없다는 점에서 포인터는 "타입 안전"이 아닙니다.

예를 들어 다음 코드를 살펴보십시오.

int* p1 = GetAPointer();

이것은 GetAPointer가 int *와 호환되는 형식을 반환해야한다는 점에서 형식 안전입니다. 그러나 * p1이 실제로 int를 가리킬 것이라는 보장은 아직 없습니다. char, double 또는 임의 메모리에 대한 포인터 일 수 있습니다.

그러나 참조는 특정 개체를 가리 킵니다. 객체는 메모리에서 이동할 수 있지만 참조는 무효화 될 수 없습니다 (안전하지 않은 코드를 사용하지 않는 한). 이 점에서 참조는 포인터보다 훨씬 안전합니다.

string str = GetAString();

이 경우 str은 두 가지 상태 중 하나를가집니다. 1) 객체를 가리 키지 않으므로 null이거나 2) 유효한 문자열을 가리 킵니다. 그게 다야. CLR은이를 보장합니다. 포인터에 대해서는 할 수없고 그렇지 않을 것입니다.


참조는 "추상적 인"포인터입니다. 참조로 산술을 할 수없고 그 값으로 낮은 수준의 트릭을 할 수 없습니다.


먼저 sematics에서 "Pointer"를 정의해야한다고 생각합니다. 고정 으로 안전하지 않은 코드에서 만들 수있는 포인터를 의미 합니까? 네이티브 호출 또는 Marshal.AllocHGlobal 에서 얻은 IntPtr의미 합니까? GCHandle 을 의미 합니까? 클래스, 숫자, 구조체 등 모든 것이 본질적으로 동일한 것입니다. 무언가가 저장된 메모리 주소의 표현입니다. 그리고 기록을 위해 그들은 확실히 힙에있을 수 있습니다.

포인터 (위의 모든 버전)는 고정 된 항목입니다. GC는 해당 주소에 무엇이 있는지 알지 못하므로 객체의 메모리 나 수명을 관리 할 수 ​​없습니다. 즉, 가비지 수집 시스템의 모든 이점을 잃게됩니다. 개체 메모리를 수동으로 관리해야하며 누수가 발생할 가능성이 있습니다.

반면에 참조는 GC가 알고있는 "관리 포인터"입니다. 여전히 객체의 주소이지만 이제 GC는 대상의 세부 정보를 알고 있으므로 이동, 압축, 마무리, 폐기 및 관리 환경이 수행하는 기타 모든 멋진 작업을 수행 할 수 있습니다.

실제로 가장 큰 차이점은 사용 방법과 이유입니다. 관리되는 언어의 대부분의 경우 개체 참조를 사용합니다. 포인터는 interop을 수행하는 데 유용하며 매우 빠른 작업이 거의 필요하지 않습니다.

편집 : 실제로 여기 에 관리 코드에서 "포인터"를 사용할 수 있는 좋은 예가 있습니다.이 경우에는 GCHandle이지만 AllocHGlobal을 사용하거나 고정 된 바이트 배열 또는 구조체를 사용하여 똑같은 작업을 수행 할 수 있습니다. 나는 GCHandle이 나에게 ".NET"을 더 많이 느끼기 때문에 선호하는 경향이 있습니다.


포인터는 메모리 주소 공간의 위치를 ​​가리 킵니다. 참조는 데이터 구조를 가리 킵니다. 데이터 구조는 모두 가비지 수집기 (메모리 공간 압축을 위해)에 의해 항상 (그렇게 자주는 아니지만 가끔) 이동했습니다. 또한 언급했듯이 참조가없는 데이터 구조는 잠시 후 가비지 수집됩니다.

또한 포인터는 안전하지 않은 컨텍스트에서만 사용할 수 있습니다.


포인터는 응용 프로그램의 주소 공간에있는 모든 바이트를 가리킬 수 있습니다. 참조는 .NET 환경에 의해 엄격하게 제한되고 제어 및 관리됩니다.


참조와 포인터의 주요 차이점은 포인터가 포인터로 활발하게 사용되는 경우에만 내용이 중요한 비트 모음 인 반면 참조는 비트 집합뿐만 아니라 일부 메타 데이터를 캡슐화한다는 것입니다. 그 존재를 알린 기본 프레임 워크. 포인터가 메모리의 일부 개체에 존재하고 해당 개체가 삭제되었지만 포인터가 지워지지 않은 경우 포인터가 가리키는 메모리에 액세스하려고 시도하지 않는 한 또는 포인터가 계속 존재해도 아무런 해를 끼치 지 않습니다. 포인터를 사용하려는 시도가 없으면 그 존재를 신경 쓰지 않습니다. 반대로 .NET 또는 JVM과 같은 참조 기반 프레임 워크에서는 시스템이 항상 존재하는 모든 객체 참조를 식별 할 수 있어야하며 존재하는 모든 객체 참조는 항상null 또는 적절한 유형의 개체를 식별합니다.

각 개체 참조는 실제로 (1) 식별하는 개체의 필드 내용과 (2) 동일한 개체에 대한 다른 참조 집합의 두 가지 정보를 캡슐화합니다. 시스템이 객체에 존재하는 모든 참조를 신속하게 식별 할 수있는 메커니즘은 없지만 객체에 존재하는 다른 참조 집합이 참조로 캡슐화되는 가장 중요한 요소 일 수 있습니다 (특히 다음과 같은 경우에 해당됨). 유형의 Object사물은 잠금 토큰과 같은 것으로 사용됩니다.) 시스템은에서 사용하기 위해 각 객체에 대해 몇 비트의 데이터를 유지하지만 객체에 GetHashCode존재하는 참조 집합을 넘어서는 실제 ID가 없습니다. X객체에 대한 유일한 현존 참조를 보유하는 경우X동일한 필드 내용을 가진 새 개체에 대한 참조를 사용하면에서 반환 된 비트를 변경하는 것 외에는 식별 가능한 효과가 없으며 GetHashCode()해당 효과조차 보장되지 않습니다.


저는 개발자가 포인터 개념 , 즉 간접 을 이해하는 것이 중요하다고 생각합니다 . 그렇다고 반드시 포인터를 사용해야한다는 의미는 아닙니다. 그것은 이해하는 것도 중요 기준의 개념 로부터 다릅니다 포인터의 개념 , 참조의 구현은 거의 항상 비록 단지 미묘하지만 입니다 포인터.

즉, 참조를 보유하는 변수는 객체에 대한 포인터를 보유하는 포인터 크기의 메모리 블록입니다. 그러나이 변수는 포인터 변수를 사용할 수있는 것과 같은 방식으로 사용할 수 없습니다. C # (및 C 및 C ++, ...)에서 포인터는 배열처럼 인덱싱 될 수 있지만 참조는 그렇지 않습니다. C #에서 참조는 가비지 수집기에 의해 추적되지만 포인터는 추적 될 수 없습니다. C ++에서는 포인터를 다시 할당 할 수 있지만 참조는 할당 할 수 없습니다. 구문 적으로나 의미 적으로 포인터와 참조는 상당히 다르지만 기계적으로는 동일합니다.


포인터를 다소 복잡하게 만드는 것은 그것이 무엇인지가 아니라 포인터로 무엇을 할 수 있는지입니다. 그리고 포인터에 대한 포인터에 대한 포인터가있을 때. 정말 재미있어지기 시작할 때입니다.


One of the biggest benefits of references over pointers is greater simplicity and readability. As always when you simplify something you make it easier to use but at the cost of flexibility and control you get with the low-level stuff (as other people have mentioned).

Pointers are often criticized for being 'ugly'.

class* myClass = new class();

Now everytime you use it you have to dereference it first either by

myClass->Method() or (*myClass).Method()

Despite losing some readability and adding complexity, people still needed to use pointers often as parameters so you could modify the actual object (instead of passing by value) and for the performance gain of not having to copy huge objects.

To me this is why references were 'born' in the first place to provide the same benefit as pointers but without all that pointer syntax. Now you can pass the actual object (not just its value) AND you have a more readable, normal way of interacting with the object.

MyMethod(&type parameter)
{
   parameter.DoThis()
   parameter.DoThat()
}

C++ references differed from C# / Java references in that once you assign a value to it that was it, you couldn't re-assign it (and it has to be assigned when it was declared). This was the same as using a const pointer (a pointer that could not be re-pointed to another object).

Java and C# are very high level, modern languages which cleaned up a lot of the messes that had accumulated in C / C++ over the years and pointers was definitely one of those things that needed to be 'cleaned up'.

As far as your comment about knowing pointers makes you a stronger programmer, this is true in most cases. If you know 'how' something works as opposed to just using it without knowing I would say this can often give you an edge. How much of an edge will always vary. After all, using something without knowing how it is implemented is one of the many beauties of OOP and Interfaces.

In this specific example, what would knowing about pointers help you with references? Understanding that a C# reference is NOT the object itself but points to the object is a very important concept.

#1: You are NOT passing by value Well for starters when you use a pointer you know that the pointer holds just an address, that's it. The variable itself is almost empty and that's why it's so nice to pass as arguments. In addition to the performance gain, you are working with the actual object so any changes you make are not temporary

#2: Polymorphism / Interfaces When you have a reference that is an interface type and it points to an object, you can only call methods of that interface even though the object may have many more abilities. The objects may also implement the same methods differently.

If you understand these concepts well then I don't think you are missing too much from not having used pointers. C++ is often used as a language for learning programming because it is good to get your hands dirty sometimes. Also, working with lower-level aspects makes you appreciate the comforts of a modern language. I started with C++ and am now a C# programmer and I do feel like working with raw pointers have helped me have a better understanding on what goes on under the hood.

I don't think it is necessary for everyone to start with pointers, but what is important is that they understand why references are used instead of value-types and the best way to understand that is to look at its ancestor, the pointer.

참고URL : https://stackoverflow.com/questions/430112/what-is-the-difference-between-a-c-sharp-reference-and-a-pointer

반응형