IT박스

3 개의 주요 C ++ 컴파일러에서 프로그램이 다르게 컴파일됩니다.

itboxs 2020. 7. 20. 07:52
반응형

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);
}
  1. g ++ 4.9.2로 컴파일하면 다음과 같은 컴파일 오류가 발생합니다.

    main.cpp:16:10: error: cannot call constructor 'C::C' directly [-fpermissive]
    
  2. MSVC2013 / 2015로 성공적으로 컴파일하고 인쇄합니다. C (B *)

  3. 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는 합리적이지만 여전히 표준을 따르지 않습니다.

참고 : https://stackoverflow.com/questions/29681449/program-being-compiled-differently-in-3-major-c-compilers-which-one-is-right-

반응형