3 개의 주요 C ++ 컴파일러에서 프로그램이 다르게 컴파일됩니다. 어느 것이 옳습니까?
이전 질문에 대한 흥미로운 후속 조치 (실제 중요하지는 않지만) : C ++에서 변수를 선언 할 때 변수 이름을 괄호로 묶을 수있는 이유는 무엇입니까?
삽입 된 클래스 이름 기능 과 괄호로 선언을 결합하면 컴파일러 동작과 관련하여 놀라운 결과가 발생할 수 있음을 알았습니다 .
다음 프로그램을 살펴보십시오.
#include <iostream>
struct B
{
};
struct C
{
C (){ std::cout << "C" << '\n'; }
C (B *) { std::cout << "C (B *)" << '\n';}
};
B *y = nullptr;
int main()
{
C::C (y);
}
g ++ 4.9.2로 컴파일하면 다음과 같은 컴파일 오류가 발생합니다.
main.cpp:16:10: error: cannot call constructor 'C::C' directly [-fpermissive]
MSVC2013 / 2015로 성공적으로 컴파일하고 인쇄합니다.
C (B *)
clang 3.5로 성공적으로 컴파일하고 인쇄합니다.
C
어떤 질문이 옳은가? :)
(하지만 기술적으로 typedef를 사용하여 유형을 변경 한 후 변수 선언을 중지하는 msvc 방법과 csvc 버전으로 강력하게 흔들 렸습니다.)
적어도 C ++ 11 조회 규칙에 따라 GCC가 정확합니다. 3.4.3.1 [class.qual] / 2는 내포 된 이름 지정자가 클래스 이름과 동일하면 주입 된 클래스 이름이 아닌 생성자를 참조하도록 지정한다. 예제를 제공합니다.
B::A ba; // object of type A
A::A a; // error, A::A is not a type name
struct A::A a2; // object of type A
MSVC 는 생성자 매개 변수로 임시 C
를 만드는 함수 스타일 캐스트 식으로 잘못 해석하는 것처럼 보입니다 y
. Clang은이 y
를 type 이라는 변수의 선언으로 잘못 해석합니다 C
.
오류가 발생하므로 G ++이 정확합니다. 생성자가 new
연산자 없이 이러한 형식으로 직접 호출 될 수 없기 때문 입니다. 코드에서를 호출하더라도 C::C
생성자 호출처럼 보입니다. 그러나 C ++ 11 표준 3.4.3.1에 따르면 이는 유효한 함수 호출 또는 유형 이름이 아닙니다 ( Mike Seymour의 답변 참조 ).
Clang은 올바른 함수를 호출하지 않기 때문에 잘못되었습니다.
MSVC는 합리적이지만 여전히 표준을 따르지 않습니다.
'IT박스' 카테고리의 다른 글
Maven Repo에 Nexus 또는 Artifactory를 사용해야합니까? (0) | 2020.07.21 |
---|---|
Chrome : 백그라운드 탭에서 시간 초과 / 간격이 일시 중지 되었습니까? (0) | 2020.07.20 |
TPL Task 객체에서 Dispose ()를 호출하지 않는 것이 허용됩니까? (0) | 2020.07.20 |
개자식 주사에 대한 대안이 있습니까? (0) | 2020.07.20 |
SecItemAdd 및 SecItemCopyMatching은 오류 코드 -34018 (errSecMissingEntitlement)을 반환합니다. (0) | 2020.07.20 |