void*
C ++에서를 합법적으로 사용 합니까? 아니면 C가 있었기 때문에 도입 되었습니까?
내 생각을 요약하자면 :
입력 : 여러 입력 유형을 허용하려면 함수와 메서드를 오버로드 할 수 있습니다. 대신 공통 기본 클래스 또는 템플릿을 정의 할 수 있습니다 (답변에 언급 해 주셔서 감사합니다). 두 경우 모두 코드가 더 설명적이고 오류 발생 가능성이 적습니다 (기본 클래스가 정상적인 방식으로 구현 된 경우).
출력 : void*
알려진 기본 클래스에서 파생 된 것보다 수신 하고 싶은 상황을 생각할 수 없습니다 .
내가 의미하는 바를 명확히하기 위해 :에 대한 유스 케이스가 있는지 구체적으로 묻는 것이 아니라 최선의 선택 또는 사용 가능한 선택 void*
이있는 경우가 있는지 여부 를 구체적으로 묻지 않습니다 void*
. 아래의 여러 사람들이 완벽하게 답변했습니다.
답변
void*
적어도 ::operator new
(또한 모든 operator new
…) 의 결과 및 malloc
배치 new
연산자 의 인수로 필요합니다 .
void*
모든 포인터 유형의 공통 상위 유형으로 생각할 수 있습니다. 따라서 그것은 정확히에 대한 포인터를 의미하는 것이 아니라 void
어떤 것에 대한 포인터를 의미합니다.
BTW, 관련되지 않은 여러 전역 변수에 대한 일부 데이터를 유지하려면 std::map<void*,int> score;
global int x;
and double y;
and std::string s;
do score[&x]=1;
and score[&y]=2;
and 를 선언 한 후 일부 를 사용할 수 있습니다.score[&z]=3;
memset
void*
주소를 원함 (가장 일반적인 주소)
또한 POSIX 시스템에는 dlsym이 있으며 반환 유형은 분명히void*
답변
를 사용하는 데는 여러 가지 이유가 있으며 void*
가장 일반적인 3 가지 이유는 다음과 같습니다.
void*
인터페이스에서 사용하여 C 라이브러리와 상호 작용- 유형 삭제
- 형식화되지 않은 메모리 표시
역순 void*
으로 char*
(또는 변형) 대신 (3) 으로 형식화되지 않은 메모리를 표시 하면 우발적 인 포인터 산술을 방지하는 데 도움이됩니다. 사용 가능한 작업이 거의 void*
없으므로 일반적으로 유용하기 전에 캐스팅이 필요합니다. 물론 char*
앨리어싱에 문제가없는 것과 매우 비슷 합니다.
Type-erasure (2)는 템플릿과 함께 C ++에서 계속 사용됩니다.
- 비 제네릭 코드는 바이너리 팽창을 줄이는 데 도움이되며 일반 코드에서도 콜드 경로에 유용합니다.
- 비 제네릭 코드는 때때로 저장을 위해 필요합니다.
std::function
그리고 당연히 당신이 다루는 인터페이스가 void*
(1)을 사용할 때 당신은 선택의 여지가 거의 없습니다.
답변
어 그래. C ++에서도 때때로 우리 void *
는template<class T*>
때로는 템플릿 확장에서 추가 코드가 너무 많은 무게 때문이다.
일반적으로 유형의 실제 구현으로 사용하고 템플릿 유형은 여기에서 상속하고 캐스트를 래핑합니다.
또한 사용자 지정 슬랩 할당 자 (운영자 새 구현)는 void *
. 이것이 g ++ void *
가 마치 크기가 1 인 것처럼 포인터 산술을 허용하는 확장을 추가 한 이유 중 하나입니다 .
답변
입력 : 여러 입력 유형을 허용하려면 함수와 메서드를 오버로드 할 수 있습니다.
진실.
또는 공통 기본 클래스를 정의 할 수 있습니다.
이것은 부분적으로 사실입니다. 공통 기본 클래스, 인터페이스 또는 이와 유사한 것을 정의 할 수 없다면 어떻게 될까요? 이를 정의하려면 소스 코드에 대한 액세스 권한이 필요하며 이는 종종 불가능합니다.
템플릿에 대해서는 언급하지 않았습니다. 그러나 템플릿은 다형성에 도움이되지 않습니다. 즉, 컴파일 타임에 알려진 정적 유형에서 작동합니다.
void*
가장 낮은 공통 분모로 간주 될 수 있습니다. C ++에서, 당신은 일반적으로 하지 않습니다 (i) 본질적으로 많은 것을 할 수없고 (ii) 거의 항상 더 나은 솔루션이 있기 때문에 .
또한 일반적으로 다른 구체적인 유형으로 변환하게됩니다. 그렇기 때문에 char *
순수한 데이터 블록이 아닌 C 스타일 문자열을 기대하고 있음을 나타낼 수 있지만 일반적으로 더 좋습니다. 이것이 다른 포인터 유형에서 암시 적 캐스트를 허용하기 때문에 void*
그보다 나은 이유 입니다 char*
.
당신은 약간의 데이터를 받고, 그것으로 작업하고, 출력을 만들어 내야합니다. 이를 달성하려면 작업중인 데이터를 알아야합니다. 그렇지 않으면 원래 해결했던 문제가 아닌 다른 문제가 발생합니다. 많은 언어에는void*
에는 문제가없고 문제가 없습니다.
또 다른 합법적 인 사용
포인터와 같은 함수로 포인터 주소를 인쇄 할 때 유형 printf
이 있어야 void*
하므로 void
* 로 캐스트해야 할 수 있습니다.
답변
예, 언어의 다른 것만 큼 유용합니다.
예를 들어, 최소한의 유연한 인터페이스를 갖기 위해 필요할 때 올바른 유형으로 정적으로 캐스팅 할 수있는 클래스 유형을 지우는 데 사용할 수 있습니다.
에서 그 응답 당신에게 아이디어를 줄 것이다 사용의 예있다.
명확성을 위해 아래에 복사하여 붙여 넣습니다.
class Dispatcher {
Dispatcher() { }
template<class C, void(C::*M)() = C::receive>
static void invoke(void *instance) {
(static_cast<C*>(instance)->*M)();
}
public:
template<class C, void(C::*M)() = &C::receive>
static Dispatcher create(C *instance) {
Dispatcher d;
d.fn = &invoke<C, M>;
d.instance = instance;
return d;
}
void operator()() {
(fn)(instance);
}
private:
using Fn = void(*)(void *);
Fn fn;
void *instance;
};
분명히 이것은 void*
.
답변
포인터를 반환하는 외부 라이브러리 함수와 인터페이스. 다음은 Ada 애플리케이션 용입니다.
extern "C" { void* ada_function();}
void* m_status_ptr = ada_function();
이것은 Ada가 당신에게 말하고 싶어했던 것에 대한 포인터를 반환합니다. 멋진 일을 할 필요가 없습니다. Ada에게 돌려 주면 다음 작업을 수행 할 수 있습니다. 사실 C ++에서 Ada 포인터를 분리하는 것은 사소한 일이 아닙니다.
답변
요컨대 C ++는 엄격한 언어 ( malloc () 와 같은 C 유물을 고려하지 않음 ) 로서 가능한 모든 유형의 공통 부모가 없기 때문에 void *가 필요합니다. 예를 들어 ObjC와 달리 object .