가장 성가신 해석
Most vexing parse가장 성가신 해석은 C++ 프로그래밍 언어로 구문 모호성 해결의 반직관적인 형태입니다.특정 상황에서 C++ 문법은 객체 파라미터의 작성과 함수 타입의 지정을 구별할 수 없습니다.이러한 경우 컴파일러는 해당 행을 함수 유형 사양으로 해석해야 합니다.
발생.
"가장 짜증나는 해석"이라는 용어는 Scott Meyers가 2001년에 쓴 그의 저서 Effective [1]STL에서 처음 사용되었습니다.C에서는 이례적인 현상이지만 C++[2]11에서는 균일한 초기화가 도입될 때까지 C++에서는 매우 일반적인 현상이었습니다.
예
C스타일의 캐스트
함수 캐스트가 변수를 초기화하기 위한 식을 변환하려는 경우 다음과 같은 간단한 예가 나타납니다.
무효 f(더블 my_dbl) { 인트 i(인트(my_dbl)); }
위의 2행은 애매합니다.하나의 가능한 해석은 변수를 선언하는 것이다. i
변환함으로써 생성되는 초기값으로 my_dbl
에 대해서int
단, C는 함수 파라미터 선언 주위에 여분의 괄호를 사용할 수 있습니다.이 경우,i
는 대신 다음과 같은 함수 선언입니다.
// i라는 함수는 정수를 취하여 정수를 반환합니다. 인트 i(인트 my_dbl);
이름 없는 임시
보다 상세한 예는 다음과 같습니다.
구조 타이머 {}; 구조 타임키퍼 { 명시적 타임키퍼(타이머 t); 인트 get_time(); }; 인트 주된() { 타임키퍼 time_keeper(타임키퍼)(타이머()); 돌아가다 time_keeper(타임키퍼).get_time(); }
회선
타임키퍼 time_keeper(타임키퍼)(타이머());
애매한 것은 어느 쪽인가로 해석될 수 있기 때문에
- 변수의 변수 정의
time_keeper
계급의TimeKeeper
, 클래스의 익명 인스턴스로 초기화되었습니다.Timer
또는 - 함수의 함수 선언
time_keeper
타입의 오브젝트를 반환한다.TimeKeeper
또한 단일(유형) 매개 변수를 가지며, 그 유형은 (a에 대한[Note 1]) 함수로 입력 및 반환을 받지 않습니다.Timer
물건들.
C++ 표준에는 두 번째 해석이 필요하며, 이는 위의 9행과 일치하지 않습니다.예를 들어 Clang++는 가장 성가신 해석이 9번째 줄에 적용되어 다음 [3]줄에 오류가 발생했음을 경고합니다.
$ clang + + time _ keeper . cc timekeeper.cc:9:25 : warning : 괄호가 함수 선언 [ - Wvexing - parse ]TimeKeeper ( Timer ) ; ^ ~~~~ timekeeper.cc:9:26 :주: 변수 TimeKeeper Time_keeper ( Timer ) ; ^ ~ ~ ~ ~ ~ ^ ( ) )의 시간을 선언하기 위해 괄호를 추가합니다.er.cc:10:21: 오류: 회원 참조 기반 유형 'TimeKeeper (Timer (*))'가 구조 또는 유니언 반환 time_keeper.get_time()이 아닙니다. ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
솔루션
이러한 애매한 선언에 대한 필요한 해석은 의도된 [4][5]것이 거의 아니다.C++의 함수 유형은 보통 typedef 뒤에 숨겨지며 일반적으로 명시적인 참조 또는 포인터 한정자를 가집니다.대체 해석을 강제하기 위해 일반적인 방법은 다른 객체 생성 또는 변환 구문입니다.
유형 변환 예제에서는 캐스트에 사용할 수 있는 두 가지 대체 구문이 있습니다. "C-style cast"
// 유형 int 변수를 선언합니다. 인트 i((인트)my_dbl);
또는 이름 있는 출연자:
인트 i(static_cast< >인트>(my_dbl));
변수 선언 예에서는 (C++11 이후) 권장되는 방식은 균일한(괄호) [6]초기화입니다.이것에 의해, 타입명 전체를 생략할 수도 있습니다.
//다음 작업 중 하나: 타임키퍼 time_keeper(타임키퍼)(타이머{}); 타임키퍼 time_keeper(타임키퍼){타이머()}; 타임키퍼 time_keeper(타임키퍼){타이머{}}; 타임키퍼 time_keeper(타임키퍼)( {}); 타임키퍼 time_keeper(타임키퍼){ {}};
C++11 이전에는 의도한 해석을 강제하기 [5]위한 일반적인 기술은 추가 괄호 또는 복사 초기화였습니다.
타임키퍼 time_keeper(타임키퍼)( /*MVP 회피*/ (타이머()) ); 타임키퍼 time_keeper(타임키퍼) = 타임키퍼(타이머());
후자의 구문에서는 복사 초기화가 [7]컴파일러에 의해 최적화될 가능성이 있습니다.C++17 이후, 이 최적화는 [8]보증되고 있습니다.
메모들
레퍼런스
- ^ Meyers, Scott (2001). Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library. Addison-Wesley. ISBN 0-201-74962-9.
- ^ Coffin, Jerry (29 December 2012). "c++ - What is the purpose of the Most Vexing Parse?". Stack Overflow. Archived from the original on 17 January 2021. Retrieved 2021-01-17.
- ^ Lattner, Chris (5 April 2010). "Amazing Feats of Clang Error Recovery". LLVM Project Blog. The Most Vexing Parse. Archived from the original on 26 September 2020. Retrieved 2021-01-17.
- ^ DrPizza; Prototyped; wb; euzeka; Simpson, Homer J (October 2002). "C++'s "most vexing parse"". ArsTechnica OpenForum. Archived from the original on 20 May 2015. Retrieved 2021-01-17.
- ^ a b Boccara, Jonathan (2018-01-30). "The Most Vexing Parse: How to Spot It and Fix It Quickly". Fluent C++. Retrieved 2021-01-17.
- ^ Stroustrup, Bjarne (19 August 2016). "C++11 FAQ". www.stroustrup.com. Uniform initialization syntax and semantics. Retrieved 2021-01-17.
- ^ "Myths and urban legends about C++". C++ FAQ. What is copy elision? What is RVO?. Archived from the original on 17 January 2021. Retrieved 2021-01-17.
- ^ Devlieghere, Jonas (2016-11-21). "Guaranteed Copy Elision". Jonas Devlieghere. Retrieved 2021-01-17. 단, 에 기재되어 있는 경고에 주의해 주십시오.
외부 링크
- C++03 표준 최종 초안에서의 논의(© 8.2 모호성 해결 [dcl.ambig.res] 참조):https://web.archive.org/web/20141113085328/https://cs.nyu.edu/courses/fall11/CSCI-GA.2110-003/documents/c++2003std.pdf
- 직접 초기화 시 CppReference(가장 성가신 해석에 취약한 종류):https://en.cppreference.com/w/cpp/language/direct_initialization