문제

무효에 대한 참조를 갖는 것이 왜 불가능합니까?C++ 표준에서 내가 찾은 유일한 것은 다음 줄입니다. 8.3.2.1

"참조 유형을 지정하는 선언자 이력서 무효"는 형식이 잘못되었습니다.

왜 그런가요?왜 나는 다음을 허용하는 "일반" 함수를 작성할 수 없습니까? void&?

분명히 말하자면, 템플릿을 사용하는 것보다 void에 대한 참조를 사용하는 것이 더 나을 수 있는 유용한 응용 프로그램을 염두에 두고 있지는 않지만 이 구성을 금지하는 근거가 궁금합니다.


조금 더 명확하게 설명하자면, void에 대한 참조를 "있는 그대로" 사용하는 것은 void에 대한 참조를 역참조하는 것만큼 의미가 없다는 것을 이해합니다.그러나 참조 대상으로 캐스팅할 수는 있습니다.어떤 종류의 그것을 사용하려면 안되나요?사실, 다음 스니펫이 왜 작동하는지 모르겠습니다...

void foo(void *data)
{
    int *i = reinterpret_cast<int*>(data);
    // do something with i
}

...이것은 할 수 없습니다:

void foo(void &data)
{
    int &i = reinterpret_cast<int&>(data);
    // do something with i
}
도움이 되었습니까?

해결책

void에 대한 언급이 있다면 어떻게 하시겠습니까? 숫자, 캐릭터, 포인터 또는 그와 비슷한 것이 아닙니다. 가상의 일반 기능은 주소를 제외하고는 그 크기가 아닌 제외하고는 작업을 수행 할 수 없습니다.

"void"에는 두 가지 용도가 있습니다. 어느 경우에도 주소가있을 수 있다는 점을 제외하고는 공허 무언가에 대해 아무 말도 할 수 없습니다.

무언가가 유용 할 수있는 방법을 생각할 수없고, 내가 할 수 없다면, 그것은 적어도 무언가가 쓸모 없다는 증거이며, 그것은 적어도 이론적 근거의 일부일 수 있습니다.

다른 팁

먼저 자신을 물어보십시오. 공허 포인터를 어떻게 참조 할 것인가?

void *p = /*something*/ ;
cout << *p << endl;

위의 코드는 의미가 없다. 정의상, 컴파일러는 공허 *가 무엇을 가리키는 지 알지 못하므로이를 피할 수는 없습니다. 캐스팅을 통해 - 그러나 컴파일러는 할 수 없습니다.

빈 공간에 대한 참조는 동일한 문제로 인해 고통을 겪습니다. 정의상에 따르면 지적한 데이터에는 유형이 없으므로 의미있는 방식으로 참조 할 수 없습니다.

참조하려면 - 프로그래머는 다른 유형으로 캐스팅해야합니다. 그러면 이에 대한 참조를 참조 할 수 있습니다.

내가 원했던 것만 큼 이것을 설명했는지 확실하지 않습니다.

루벤, 어떤 생각이 있습니까?

편집하다: 편집에 응답합니다.

void* 데이터를 전달하는 첫 번째 기능을 사용하십시오. 데이터는 완벽하게 유효한 항목이거나 계산할 수 있거나 구현 된 일부 로깅이있는 경우 로그인 할 수 있습니다.

logger << data;

그리고 주소 데이터 포인트를 얻을 수 있습니다. 데이터를 대기하려고하면 컴파일러에 오류가 발생합니다 (C ++ 컴파일러는 순간에 편리하지 않으므로 실제 오류는 확실하지 않음). 예를 들어

void* data = /* some assignment */;
logger << *data; // compiler error.

이제 컴파일러는 어떤 이유로 든 무효*를 불신하게하지 않으며 (의미가 없습니다), 참조이기 때문에 Void & Data에 대한 참조를 의미합니다. 항상 암시 적으로 불쾌감을 느낍니다. 컴파일러를 사용하면 한 번의 작업에서 무효*를 피할 수 없으므로 끊임없이 피할 수 없습니다.

void& data = /* some assignment *.;
logger << data; // means same as logger << *data above

당신은 할 수 없습니다 아무것 데이터에 제외하고 주소를 가져 가면 랑그에 내장 된 완벽하고 안전한 방법이 있습니다.

void* data;

이것이 더 이상 이해가 되나요?

참조는 무언가의 인스턴스에 대한 참조입니다. 무언가의 인스턴스는 유형이 될 수 없습니다 void. 무언가의 모든 인스턴스에는 특정 유형 (및 기본 유형)이 있어야합니다.

다음은 다음과 같은 다른 것들에 대한 요약과 내가 생각한 것입니다.

기준과 관련된 두 가지 주요 이유가 허용되지 않습니다


1 그들은 완전히 쓸모가 없었을 것입니다.

실제로, 우리가 C의 시간을 되돌아 보면, 무효 포인터는 두 가지 목적을 가졌다.

  • 메모리 관리 (예 : Malloc)
  • 일반성 (모든 유형의 인수를 받아 들일 수있는 작문 기능)

C ++가 나왔을 때, 템플릿은 일반성을 구현하기위한 최상의 솔루션이되었습니다. 그러나 사용자 정의 메모리 관리가 여전히 가능해야했으며 C ++와 C 사이의 상호 운용성이 큰 관심사 였으므로 무효가 유지되었습니다. 가상의 무효 기준은 메모리 관리에 도움이되지 않으며, 일반성은 이미 다루었으므로 기본적으로 거의 사용되지 않을 것입니다 (아래에 설명 된 널리시의 보장을 제외하고).

2 당신은 그것으로 아무것도 할 수 없을 것입니다

공극 포인터를 사용할 때는이를 피할 수 없습니다. 참고 문헌의 경우에 전달되면 (항상 가상의) 공허 참조를 사용할 수 없습니다. 그래서

void *data = // something
// using *data and data-> is forbidden

void &data = // something
// using data is forbidden

그러나, 우리는 참조가 "복제"될 필요가없는 사용 사례를 생각할 수 있지만 (이 문구는 끔찍하지만 내 요점을 얻습니다), 주소 만 가져갈 수있는 곳. 다음 기능이 있다고 가정 해 봅시다.

void foo(void *dataptr)
{
    assert(dataptr != NULL); // or != 0
    // do something with dataptr
}

이 성가신 주장을 피하기 위해이 기능을 이런 식으로 쓸 수 있습니다.

void foo(void &dataref)
{
    void *data = &dataref;
    // do something with data
}

그러나 이것이 작동하기 위해 &dataref 동등해야합니다 dataptr, 그렇지 않습니다: &dataref 동일합니다 &*dataptr!

따라서 주소를 복용하더라도 적어도 개념적으로 불쾌감을 의미합니다 (무대 뒤에서 첫 번째 동등성은 아마도 사실이지만 의미 론적 수준에서는 그렇지 않습니다). 결과적으로, 우리가 데이터를 만들 수있는 사용법은 전혀 없으므로 공허 참조는 수차입니다.

기술적으로 말하면, 보장되는 것은 객체에 대한 참조가 그것에 대한 별명이라는 것입니다. 후드 참조 인수 아래에서 통과하는 것은 포인터로 수행된다는 것은 구현 세부 사항입니다. 이는 주소 인 & 운영자를 재사용하는 참조로 인해 혼란 스러울 수 있지만, 운영자는 실제로 다른 컨텍스트에서 다른 의미를 가지고 있음을 명심해야합니다 (변수 또는 매개 변수 선언에서는 참조 유형을 나타냅니다. 그렇지 않으면 주소는 주소입니다. 비트와 비트를 제외하고). 기술적으로 객체에 대한 별명 일 뿐이므로 Worrier가 설명했듯이 참조는 '항상 불쾌감을 느낍니다'.

좋아, 한 가지는 이것에 대해 나를 괴롭히는 것입니다. A의 아이디어 void*, 위에서 언급했듯이 주소가 포함 된 유효한 변수가 있지만 유형은 무시되고 있습니다. 주소 데이터로 여전히 작업 할 수 있기 때문에 이것은 허용되는 것 같습니다.이 맥락에서 유형은 다소 불필요한 (또는 덜 중요합니다). 시도하고 시도하기 때문에 불쾌감이 나쁘다 회원에 액세스하십시오 예를 들어 이해가되지 않습니다 p.mem. 우리는 어떤 클래스를 언급 해야하는지, 따라서 메모리가 따라야 할 메모리를 알지 못합니다.

그러나 그것은 의미가있는 것 같습니다 p 그 자체로는 객체만을 언급하지만 데이터는 없기 때문에 괜찮을 것입니다. 수업 정보가 필요하지 않습니다. 나는 이것에 전혀 쓸모가 없다는 것을 이해하지만, 상황이 무너질 때를 정의하는 것이 중요합니다. 이 개념을 허용, C ++ 참조 (지속적으로 부정확하지만 아무것도 액세스하지는 않음) void& ref = static_cast< &void >(obj) 또한 의미가 있으므로 무효 참조를 허용합니다. 나는 누군가가 담당자들과 그것을 받아 들여야한다고 말하지는 않지만, "말이되는"관점에서 볼 때, 그것은 정확해 보일 것입니다.

Luc Touraille이 위에서 지적했듯이 (적어도 이것은 내 해석입니다) 구현 될 수 있지만 문제는 의미 론적입니다. 내가 올 수있는 합리적인 설명은 객체 변수가 메모리 시퀀스의 "태그"이기 때문에 유형은 중요한 의미 값이라는 것입니다. 따라서 주소 값이있는 변수로 생각되는 포인터는이 유형을 정의하는 데 중요하지 않은 다소 불필요한 것으로 취급합니다.

누구든지 그것에 동의할까요?

참조를 참조 된 포인터로 생각할 수 있습니다. 구문 적으로 당신은 참조가 포인터가 아닌 것처럼 참조를 취급합니다 : 당신은 그것을 연기하기 위해 * 연산자가 필요하지 않으며, 당신은 사용할 수 있습니다. -> 회원에 접근하는 대신.

그러나 반드시 a void 바늘. 바이너리 웜 리어 (Binary Worrier)에서 지적한 바와 같이, 그렇게하려고 노력하면 컴파일러 오류가 발생할 수 있습니다. 또한 불균형 공간 포인터를 가질 수 없다면 공허 참조를 가질 수는 없습니다.

만약 그렇다면, 그들은 시맨 적으로 포인터에서 분리되지 않으며 구문 설탕에 해당 할 것입니다. 언급은 "이 유형의 무언가를 언급합니다."라고 말합니다. 무효 또는 널리 참조를 허용하면 포인터와의 차이가 약화됩니다.

물론, 참조는 더 이상 존재하지 않는 객체를 참조 할 수 있지만 예외입니다.

다음은 ~ 아니다 무효 참조 개념에 대한 방어.나는 그것을 야생의 일화로 제공합니다.이상한 냄새가 나지 않는지 스스로에게 물어보세요.

우리 회사는 C++를 상업적으로 사용한 최초의 회사 중 하나였으며 처음에는 다음을 사용하여 컴파일했습니다. 정면.초기 개발자들은 여전히 ​​언어를 배우고 있었고 일반적으로 책에 있는 모든 트릭을 사용하고 있었습니다(연산자는 어디에나 있습니다!).그들이 멋지다고 생각한 트릭은 다음과 같습니다.

void Foo::something(int action, ostream &os = *(ostream *)0)
{
   ostream *os_p = &os;
   if (&os == (ostream *)0) {
      os_p = &cerr;
   }
   // continue with method
}

따라서 여기에는 무효 참조가 아니라 잠재적으로 다음과 같은 형식화된 참조가 있습니다. 무효의 제본!잠시 생각해 보면 아마도 이 특정 관용구에 대한 더 나은 대안이 제시될 것입니다...

무효의 정의상, 존재하지 않는 것이므로, 그것을 주주하는 것은 논리적이지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top