2009-07-18 5 views
6

누군가 나에게 설명해 주시겠습니까? 왜이 코드는 "created \ n42"대신 "42"만 인쇄합니까? 왜이 코드는 42 개만 인쇄합니까?

#include <iostream> 
#include <string> 
#include <memory> 

using namespace std; 

class MyClass 
{ 
public: 
    MyClass() {cout<<"created"<<endl;}; 
    int solution() {return 42;} 
    virtual ~MyClass() {}; 
}; 

int main(int argc, char *argv[]) 
{ 
    auto_ptr<MyClass> ptr; 
    cout<<ptr->solution()<<endl; 
    return 0; 
} 

은 BTW 나는 솔루션에 다른 값이 코드를 시도하고 난 항상 "오른쪽"값을 얻을, 그래서 임의의 운이 값이 될 것 같지 않습니다.

+13

내 충고는 "은하계의 히치하이커 안내서"를 참조하십시오. – NoMoreZealots

답변

27

정의되지 않은 동작을 나타 내기 때문에 널 포인터를 역 참조합니다.

당신이 말할 때 :

auto_ptr<MyClass> ptr; 

는 아무것도 가리 키지 않는 autopointer을 만들 수 있습니다. 당신이 말하는 그런 경우

MyClass * ptr = NULL; 

:이 말에 동등이 널 포인터 역 참조

cout<<ptr->solution()<<endl; 

을. 그렇게하는 것은 C++에서 정의되지 않았습니다. 구현을 위해서는 제대로 작동하는 것 같습니다.

+1

그것은 받아 들여지는 대답의 흥미있는 무역 (하하)이었다. : P – GManNickG

+0

하지만 내 것이 처음이었다 :-) –

+0

오, 나는 불평하지 않고있다 :) 나는 내가 제출 한 후 너의 것을 올렸고, 나는 그릴 때 느렸다. – GManNickG

2

당신은 그것은 당신이 바로, 생성자를 호출하지 않는 것 같다 응답의 xD

에 대한 질문을 모르기 때문에?

+0

그게 내가 생각한거야 ... – CalebHC

21

std::auto_ptr은 자동으로 개체를 만들지 않습니다. 즉, 대기 상태에있는 ptr은 null로 초기화됩니다. 이를 역 참조하는 것은 정의되지 않은 동작이며, 결과적으로 운이 좋으면 42가됩니다.

실제로 객체 작성하는 경우 :

int main(int argc, char *argv[]) 
{ 
    auto_ptr<MyClass> ptr(new MyClass); 

    cout << ptr->solution() << endl; 

    return 0; 
} 

을 당신이 기대하는 출력을 얻을 것이다.

+3

나는 항상 42가 모든 것에 대한 해답이라는 것을 알았지 만, null 포인터 또한 그것을 알고 있다고 생각하지 않았다. 감사! 왜 이것이 세그멘테이션 오류를 발생시키지 않습니까? – rlazo

+2

정의되지 않은 동작이 작동하므로 작동하지 않거나 컴퓨터를 다시 포맷 할 수 있습니다. 아마도 그것이 효과가 있었던 이유는 당신이 실제로 그 반원들에게 작별 인사를하지 않았기 때문입니다. 컴파일러는 당신이'MyClass :: solution'에 접근하고 있다고 봅니다. 그것은'this' 포인터에 대해 0을 넣습니다. 왜냐하면 그것은 그것이 무엇인지, 함수에 들어가서 결과로 42를 얻고 반환하기 때문입니다. 당신의 clasas에게 개인 응답'int answer'을주고, 생성자에서 42로 설정하고, 그것을'solution()'으로 돌려 주면, 이제는 실제로'this' 포인터를 사용하려고하기 때문에 충돌을 보게 될 것입니다 . – GManNickG

+1

@rlazo : 솔루션 함수가 멤버 변수에 액세스하지 않아 "this"포인터가 함수 내에서 사용되지 않으므로 segfault가 발생하지 않습니다. –

2

개체의 인스턴스를 만들지 않아도됩니다.
스마트 포인터 만 만듭니다.

NULL 포인터를 참조 해제하는 메서드를 호출하면 Neil이 이제 정의되지 않은 동작을한다는 것을 알 수 있습니다. 그러나 코드가 모든 멤버 변수에 액세스하지 않으므로 운 좋게 충돌하지 않습니다.

이 시도 : ptr가 초기화되지 않은 그리고 당신이 운이 좋다

auto_ptr<MyClass> ptr(new MyClass); 
+0

"운 좋게"보다는 "불행하게"말할 것입니다. –

1

때문입니다. 먼저 그것을 new을 호출해야합니다 : 당신은 충돌을받지 못하고있어

auto_ptr<MyClass> ptr(new MyClass); 
1

은 "솔루션"방법은 실제로 클래스 멤버를 사용하지 않기 때문에. 회원이나 물건을 돌려 주면 충돌이 일어날 수 있습니다.

3

우선 -> 연산자 인 auto_ptr은 기본적으로 포함 된 포인터로 전달됩니다.그리고 컴파일러가 다른로 전달 된 this 포인터로 매우 그들이 것처럼 비 멤버 함수를 작동 방식으로 멤버 함수를 구현하는 경향이 있습니다

MyClass* ptr = NULL; 
cout << ptr->solution() << endl; 

: 그래서 토론, main에 코드에 해당된다 함수 인수. 그래서보기의 현재 컴파일러의 관점에서, main 행위의 코드는 것처럼하십시오이없는 이유가 분명하게

int solution(MyClass* this) { return 42; } 

하는 경우 : 솔루션

MyClass* ptr = NULL; 
cout << solution(ptr) << endl; 

는 다음과 같이 작성 추락.


그러나 이미 언급했듯이 이들은 언어 표준에 명시되지 않은 컴파일러가 C++을 구현하는 방법에 대한 내부 정보입니다. 따라서 이론적으로이 코드는 한 컴파일러에서 설명 된대로 작동하지만 다른 컴파일러에서 완전히 다른 작업을 수행 할 수 있습니다.

그러나 실제로이 표준이이 동작을 보장하지 않더라도 특정 컴파일러 이 원하는 경우이를 보장 할 수 있습니다. 예를 들어, MFC는이 동작을 사용하기 때문에 Visual Studio에서 지원하지 않을 가능성은 거의 없습니다. 물론, 코드가 실제로이 동작을 보증하는지 확인하기 위해 각각의 특정 컴파일러를 조사해야합니다.

관련 문제