2009-09-08 3 views
2

이 예제를 고려하십시오개체 생성 전에 멤버 함수가 준비되어 있습니까?

#include <iostream> 

class myclass 
{ 
public: 
    void print() { std::cout << "myclass"; } 
}; 

int main() 
{ 
    myclass* p = 0x0; // any address 

    p->print(); // prints "myclass" 
} 

나는 myClass 타입의 객체를 통해 멤버 함수 print를 호출하지 않았다. 대신 포인터를 메모리의 임의의 위치로 호출했습니다. 이것은 정의 된 행동입니까? 즉, myclass 유형의 객체를 만들기 전에 멤버 함수가 실행되도록 보장됩니까?

+1

null로 작업하는 멤버 함수가 다른 질문을 던졌습니다. http://stackoverflow.com/questions/1148328/why-does-this-code-only-print-42/ – GManNickG

답변

11

null (0) 포인터를 역 참조하면 정의되지 않은 동작이 호출됩니다. 프로그램은 예상대로 작업을 포함하여 원하는 모든 작업을 수행 할 수 있습니다.

print() 멤버 함수가 멤버 변수를 참조하지 않았으므로 (여기에는 아무 것도 없음) 부분적으로 여기에서 벗어나지 만 컴파일러는 여전히 충돌 할 수있는 코드를 생성 할 수 있습니다. 그리고 멤버 함수가 멤버 변수를 참조하면 정의되지 않은 동작이 심각하게 발생합니다. 컴파일러, 컴파일러, 버전, 플랫폼, 플랫폼에 따라 달라질 수있는 정의되지 않은 동작을 실행하기 때문에 수행 할 수있는 작업의 범위를 찾아내는 것은 유용하지 않습니다.

+0

감사. 컴파일러가 일부 코드에서 사용되지 않으면 사용되지 않는 클래스를 전체적으로 제거 할 수 있다고 말할 수 있습니까? – AraK

+1

다소 별개의 질문이지만, 코드를 사용할 수 없다는 것을 입증 할 수 있다면 옵티마이 저가 사용하지 않는 클래스를 제거 할 수 있다고 생각합니다. 무언가가 사용되지 않는다는 것을 증명하는 것은 어렵다. 사용되지 않고 최적화 된 것으로 보이는 것을 참조하려고하는 공유 라이브러리를 동적으로로드 할 수도있다. 아마 나쁜 디자인을 구성하지만, 컴파일러는 코드가 잘못 설계 되었기 때문에 코드를 깨뜨리지 않아야합니다. (가능하다면 세상을 큰 도움이 될 것이지만!). –

+1

+1,하지만 print()가 가상이라면 더 심각하게 정의되지 않은 동작을 얻을 것이라고 덧붙이겠다. –

2
당신은 당신의 print() 기능을 변경하면 상황 계몽 도움이 될 수 있음을 알 수 있습니다

:이 0 될 것입니다 귀하의 예제에서 C++ this 포인터의 값을 출력

void print() { std::cout << "myclass, this=" << this; } 

(또는 당신이 p을 설정 무엇이든) . 클래스의 데이터 멤버에 액세스하는 것은 this의 역 참조와 동일하며 유효하게 구성된 인스턴스 인 myclass을 가리 키지 않으면 정의되지 않은 동작으로 연결됩니다. 당신이 virtual로 함수를 선언하는 경우

또한 문제로 실행됩니다 :

virtual void print() { std::cout << "myclass"; } 

구현 아마 충돌하기 전에 아무것도 인쇄되지 것입니다. 그 이유는 컴파일러가 virutal 함수를 호출 할 때 객체 vtable을 볼 코드를 생성하여 실제로 호출 할 함수를 발견하기 때문입니다. 유효한 개체가 없으면 충돌이 발생할 수 있습니다.

관련 문제