다음 프로그램을 고려하세요.
<code class="cpp">#include <iostream> class Demo { public: static void func() { std::cout << "func() called" << std::endl; } static int num = 9; }; int main() { Demo* d = nullptr; d->func(); std::cout << d->num << std::endl; return 0; }
이 프로그램은 오류 없이 컴파일되고 실행되지만, 널 포인터를 통해 정적 멤버에 액세스하는 것은 일반적으로 정의되지 않은 동작으로 간주됩니다. 이것이 허용되는 이유는 무엇입니까?
TL;DR:
널 포인터를 통한 간접 참조가 허용되지 않기 때문에 해당 프로그램은 정의되지 않은 동작을 트리거하지 않습니다. 유효한 개체 ID에 의존하는 추가 작업이 포함되지 않는 한 본질적으로 문제가 있습니다.
설명:
널 포인터를 통한 간접 참조가 본질적으로 정의되지 않은 동작인지 여부는 논쟁의 여지가 있었습니다. . 프로그램에서 유일하게 의심스러운 작업은 d->a 표현식의 평가입니다.
d->a는 포인터 역참조 규칙으로 인해 (*d).a와 동일합니다. 그러나 *d가 정의되지 않은 경우에도 *d 표현식은 계속 평가됩니다. 특히 d->a의 경우처럼 결과가 삭제될 때 더욱 그렇습니다. 이 동작은 잘 정의되어 있습니다.
정적 멤버의 동작은 null 포인터를 통해 비정적 멤버에 액세스하는 것과 다릅니다. 이는 잘못된 개체 ID를 의미하므로 실제로 정의되지 않은 동작을 트리거해야 합니다. 반면에 정적 멤버에 액세스하려면 개체 ID가 필요하지 않으며 해당 동작은 표준에 명시적으로 정의되어 있습니다.
정적 멤버 액세스 컨텍스트에서 *d 평가가 허용되므로 해당 프로그램은 아무런 해를 끼치지 않습니다. 널 포인터를 통한 간접 참조가 반드시 정의되지 않은 동작을 발생시키는 것은 아니지만 객체 ID가 필요한 추가 작업과 관련된 잠재적인 위험을 인식하는 것이 중요합니다.
위 내용은 C에서 널 포인터를 사용하여 정적 멤버에 액세스하는 것이 허용되는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!