2009-04-08 3 views
4

2,008 비주얼 스튜디오에서 시험, (클래스에 대한이 구축되지 때 볼 친숙하고 쉽게 때문에 CString을을 사용하지만 특별한 아무것도)이 코드를 고려하십시오 : 나는 C++ 표준을 알고있는 것처럼왜 이것을 컴파일합니까 (초기화 전에 함수에서 사용 했습니까)?

CString DoSomething(const CString& sString) 
{ 
    return sString; 
} 

CString sTest1 = DoSomething(sTest1); // Compiles (no warnings), fails at runtime 
CString sTest2(DoSomething(sTest2)); // Doesn't compile 
CString sTest3; sTest3 = DoSomething(sTest3); // Compiles, self-assignment, works 

, Test1 파일이 될 수 있습니다 적절한 생성자를 사용할 수 있다면 (기본적으로 첫 번째 테스트와 동일하게 생성됩니다) 컴파일 타임 최적화로 Test2에 자동으로 컴파일됩니다. 그러나 특히 Test3과 동작이 동일하지 않기 때문에 올바르게 작동합니다.

이제 Test1이 작동하지 않는 이유와 Test2가 컴파일되지 않는 이유를 이해합니다. 내가 궁금한 점은 Test1이 처음부터 컴파일되는 이유입니다. 이것은 표준, 해석을위한 개방성, VS2008 컴파일러의 결함, init-before-use 정적 검사의 결함 등으로 허용됩니까? 적어도이 경우 컴파일러가 경고를 표시하도록 강제 할 수있는 방법이 있습니까 (Test1은 VS2008에서 최대 경고 수준으로 정리 컴파일 된 것으로 나타남)? 이 구조를 허용하는 C++ 명세에 대한 정당성은 무엇입니까?

편집 : 또는 다른 방법으로 컴파일러가 Test2를 Test2로 컴파일하도록 강제 할 수 있습니까? Test2를 위해 그대로 오류 메시지를 추가 할 수

편집 : 오류 C2065 : 'sTest2': 선언되지 않은 식별자

+0

왜 두 번째 줄 트리거하는 오류 메시지를 제공하지? 알아두면 재미있을거야. 어쩌면 우리는 첫 번째 오류도 내놓을 수있는 뭔가를 만들 수 있습니다. –

+0

Test2의 오류는 표준 "기호가 정의되지 않았습니다"오류입니다. 나는 그 소식을 업데이트 할 것이다. – Nick

답변

4

sTest1에서 나타나는 동작은 C++ 표준에서 정의되지 않았습니다. 이상하고 잘못되었지만 몇 가지 컴파일러에서 컴파일됩니다. 자세한 내용은 다음 스레드에서

참조 litb의 대답은 : method running on an object BEFORE the object has been initialised?

+0

litb의 대답은 직접적인 것 같습니다. 감사합니다. 컴파일러에서 경고를 내게하는 알려진 방법이나 "아무도 이것을 쓰지 않도록하십시오"와 붙어 있습니까? – Nick

3

지난 몇 일 관련 현상에 대한 몇 가지 질문이 있었다.

내 이해는 sTest1이 초기화되지 않았지만 이미 유효한 식별자입니다 (예 : C에서 sizeof를 호출 할 수 있음). 내용이 없습니다. DoSomething을 호출하면 합법적이지만 위험한 초기화되지 않은 변수에 대한 참조가 전달됩니다.

본질적으로 문자열이어야하는 초기화되지 않은 메모리 공간 인 값에 의한 반환 (복사 생성자)을 수행하려고하므로 런타임에 반환이 문제가되는 것으로 생각됩니다. CString이 저장되는 방법에 따라 코드는 null 종결자를 찾거나 할당 된 바이트 수를 나타내는 무언가를 찾고있을 것입니다.

+0

그 행동에 맞습니다; 제 질문은 '왜'입니까? – Nick

+0

C++은 사용자가 어리석은 일을하지 못하도록하려고 시도하지 않습니다. 이를 허용하는 한 가지 이점은 아직 초기화되지 않았더라도 기술적으로 포인터를 필드에 저장할 수 있다는 것입니다. – Uri

+0

반대로 C++은 여러분이 바보 같은 일을하지 못하도록하려고 시도합니다. 이는 C보다 큰 장점 중 하나입니다. –

관련 문제