C ++에서 핸들이란 무엇입니까?


98

핸들은 일종의 포인터이지만 그렇지 않다고 들었습니다. 그러면 객체 자체가 아닌 객체에 대한 참조를 유지할 수 있습니다. 더 자세한 설명은 무엇입니까?



2
책임의 사슬 패턴을 살펴보면 "핸들"이 기본적으로 노드이고 "핸들"이 이들의 작은 집합이라는 것을 알게 될 것입니다. "마법"은 재귀에서 비롯됩니다

답변:


100

핸들은 정수 인덱스에서 커널 공간의 리소스에 대한 포인터에 이르기까지 무엇이든 될 수 있습니다. 아이디어는 리소스의 추상화를 제공하므로 리소스를 사용하기 위해 리소스 자체에 대해 많이 알 필요가 없다는 것입니다.

예를 들어 Win32 API의 HWND는 Window의 핸들입니다. 그 자체로는 쓸모가 없습니다. 정보를 수집 할 수 없습니다. 그러나 올바른 API 함수에 전달하면 다양한 트릭을 수행 할 수 있습니다. 내부적으로는 HWND를 GUI의 창 표에 대한 색인으로 생각할 수 있습니다 (반드시 구현 방법은 아닐 수 있지만 마법은 의미가 있습니다).

편집 : 질문에서 구체적으로 무엇을 요구했는지 100 % 확실하지 않습니다. 이것은 주로 순수한 C / C ++에 대한 것입니다.


14
핸들은 상태를 저장하는 데 유용 할 수 있습니다. u가 std :: vector와 같은 구조의 데이터를 가지고 있다면. 개체는 프로그램 실행 중에 다른 시간에 다른 메모리 위치에있을 수 있습니다. 이는 해당 메모리에 대한 포인터가 값을 변경한다는 것을 의미합니다. 핸들을 사용하면 변경되지 않으며 항상 개체를 참조합니다. (게임에서와 같이) 프로그램의 상태를 저장한다고 상상해보세요. 포인터 위치를 데이터에 저장하지 않고 나중에 데이터를 다시 가져 와서 해당 주소를 메모리에 가져 오려고합니다. 그러나 데이터와 함께 핸들을 저장하고 데이터와 핸들을 가져올 수 있습니다.
SinisterRainbow

HANDLE을 Linux에서 동등한 것으로 변환 할 수 있습니까? HANDLE을 사용하는 프로그램을 Windows에서 Linux로 마이그레이션해야합니다.
Cornel Verster 2015

1
그것이 무엇이든 될 수 있고 그것들을 사용하는 코드가 핸들의 유형을 정의한다는 정답입니다. 나는 후손을 위해 내 자신의 비슷한 대답을 더 간결하게 만들려고 노력했습니다. @CornelVerster-그들은 리눅스에서 동일합니다. 내 말은, OS 핸들이 아니라 개념입니다. 따라서 마이그레이션에 대한 핸들에 따라 다르거 나 마이그레이션이 필요합니다.
dyasta

@Matthew Iselin : 어떤 API 문서에서든, 그것들이 핸들러라고 정의 했나요? 그럼 우리는 그것들을 함수에 전달하는 것을 알아야합니다. 그렇지 않으면 API 문서에서 핸들러가 무엇인지 알 수있는 방법
Amin Khormaei

51

핸들은 가시적 유형이 첨부되지 않은 포인터 또는 인덱스입니다. 일반적으로 다음과 같은 내용이 표시됩니다.

 typedef void* HANDLE;
 HANDLE myHandleToSomething = CreateSomething();

따라서 코드에서 HANDLE을 불투명 값으로 전달하면됩니다.

객체를 사용하는 코드에서 포인터를 실제 구조 유형으로 캐스트하고이를 사용합니다.

 int doSomething(HANDLE s, int a, int b) {
     Something* something = reinterpret_cast<Something*>(s);
     return something->doit(a, b);
 }

또는 배열 / 벡터에 대한 인덱스로 사용합니다.

 int doSomething(HANDLE s, int a, int b) {
     int index = (int)s;
     try {
         Something& something = vecSomething[index];
         return something.doit(a, b);
     } catch (boundscheck& e) {
         throw SomethingException(INVALID_HANDLE);
     }
 }

29

핸들 일반적으로 일부 엔티티를 참조하는 방법이라는 점에서 일종의 포인터입니다.

포인터가 핸들의 한 유형이라고 말하는 것이 더 정확할 것이지만 모든 핸들이 포인터는 아닙니다.

예를 들어 핸들은 메모리 테이블에 대한 일부 인덱스 일 수도 있으며, 이는 자체적으로 일부 개체에 대한 포인터를 포함하는 항목에 해당합니다.

핵심은 "핸들"이있을 때 그 핸들이 실제로 식별하는 것을 식별하는 방법을 알거나 신경 쓰지 않는다는 것입니다. 당신이 알아야 할 것은 그것이하는 것뿐입니다.

또한 "정확히 핸들이 무엇인지"에 대한 단일 답변이 없다는 것도 분명해야합니다. 동일한 시스템에서도 다른 것에 대한 핸들은 "내부에서"다른 방식으로 구현 될 수 있기 때문입니다. 그러나 이러한 차이점에 대해 걱정할 필요는 없습니다.


6

C ++ / CLI에서 핸들은 GC 힙에있는 개체에 대한 포인터입니다. (관리되지 않는) C ++ 힙에 개체를 만드는 것은 다음을 사용하여 수행 new되며 new식 의 결과 는 "일반"포인터입니다. 관리 개체는 식을 사용하여 GC (관리) 힙에 할당됩니다 gcnew. 결과는 핸들이됩니다. 핸들에서 포인터 산술을 할 수 없습니다. 당신은 핸들을 자유롭게하지 않습니다. GC에서 처리합니다. 또한 GC는 관리되는 힙에서 개체를 자유롭게 재배치하고 프로그램이 실행되는 동안 새 위치를 가리 키도록 핸들을 업데이트 할 수 있습니다.


5

이것은 Pimpl 관용구라고도 하는 Handle-Body-Idiom 의 맥락에서 나타납니다 . 실제 데이터를 다른 클래스 객체로 유지함으로써 라이브러리의 ABI (바이너리 인터페이스)를 동일하게 유지할 수 있습니다.이 객체는 해당 클래스에 위임하는 함수로 구성된 "핸들"객체에있는 포인터에 의해 참조됩니다. " 몸".

두 개체의 일정 시간 및 예외 안전 스왑을 활성화하는 것도 유용합니다. 이를 위해서는 body 객체를 가리키는 포인터 만 바꿔야합니다.


2

핸들은 원하는대로입니다.

핸들은 일부 조회 테이블에서 사용되는 부호없는 정수일 수 있습니다.

핸들은 더 큰 데이터 집합에 대한 포인터가 될 수 있습니다.

핸들을 사용하는 코드의 동작 방식에 따라 다릅니다. 그것은 핸들 유형을 결정합니다.

' 손잡이 ' 라는 용어 가 사용되는 이유 가 중요합니다. 이는 객체의 식별 또는 액세스 유형으로 표시됩니다. 의미, 프로그래머에게 그들은 '키' 또는 무언가에 대한 액세스를 나타냅니다 .


2

HANDLE hnd; 와 같다 void * ptr;

HANDLE은 Visual Studio (Windows)의 winnt.h 파일에 정의 된 typedef입니다.

typedef void *HANDLE;

HANDLE 에 대해 자세히 알아보기


1
이는 Windows에만 적용되며 Windows 아키텍처를 통해 사용되는 여러 유형의 핸들 중 하나만 적용됩니다. 그러나, 그 입니다 에 '일반 Windows 응용 프로그램 수준의 핸들'으로 알려진 것입니다 무슨.
dyasta
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.