c++ 참조자 질문
글쓴이: ghoflvhxj / 작성시간: 금, 2018/07/13 - 9:13오후
#include <iostream> int main() { int a = 10; const int &ref = a; int *p = &a; const int *p2 = p; const int *(&pref) = p; system("PAUSE"); return 0; }
사진에서 볼 수 있듯이
포인터 참조자 pref의 값을 초기화를 할 수 없던데 왜 그럴까요?
const int &ref를 a로 값을 초기화 했던건 됐으면서 왜 안되는지 궁금합니다
Forums:
위 코드에서 ref는 상수에 대한 레퍼런스이지만
위 코드에서 ref는 상수에 대한 레퍼런스이지만 pref는 상수에 대한 레퍼런스가 아니기 때문이죠.
무슨 일이 일어나고 있는지 이해하는 데 필요한 걸 다 설명하기엔 설명해야 할 게 너무 많습니다.
일단 아무튼 잘 되는 코드 하나 받고 싶으시다면 그 정도는 해 드릴 수 있겠네요.
넹
감사합니다. 그런데 괜찮으시면 무슨 일이 일어나는지도 알 수 있을까요
일단 N4659(http://www.open-std
일단 N4659(http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2017/n4659.pdf) 기반으로.
이하 "cv1 T1" 타입에 대한 reference를 "cv2 T2"타입의 expression으로 초기화할 수 있는 조건들이 쭉 나오는데 다 필요하지도 않고 인용하기 귀찮으므로 모두 알고 싶으시면 위 표준 드래프트 문서에서 11.6.3.5를 읽어 나가시면 됩니다. 여기선 필요한 만큼만 인용하도록 하죠.
const int *(&pref) = p;
레퍼런스는 lvalue reference이고, 대상 타입은 "cv1 T1" = "const int *"이므로 cv1 = (none), T1 = "const int *"
표현식 p는 lvalue이고 타입은 "cv2 T2" = "int *"이므로 cv2 = (none), T2 = "int *"
11.6.3.5 조건 체크:
(5.1) lvalue reference인가? 예.
(5.1.1) expression이 lvalue인가? 예. "cv1 T1"이 "cv2 T2"에 reference-compatible한가? 아니오. (const int *는 int *에 reference-related 하지 않음)
(5.1.2) expression이 class type인가? (i.e., T2가 class type인가?) 아니오.
(5.2) 레퍼런스가 non-volatile const type에 대한 lvalue reference이거나 (즉 cv1가 "const"), rvalue reference인가? 아니오.
체크 끝. 모든 조건이 실패하므로
const int *(&pref) = p;
은 컴파일 되지 않습니다.재미삼아
const int &ref = a;
는 왜 되는지 볼까요? 마찬가지로...레퍼런스는 lvalue reference이고, 대상 타입은 "cv1 T1" = "const int"이므로 cv1 = "const", T1 = "int"
표현식 a는 lvalue이고 타입은 "cv2 T2" = "int"이므로 cv2 = (none), T2 = "int"
11.6.3.5 조건 체크:
(5.1) lvalue reference인가? 예.
(5.1.1) expression이 lvalue인가? 예. "cv1 T1"이 "cv2 T2"에 reference-compatible한가? 예. (T1 = T2 = "int"이므로 T1은 T2에 reference-related이고, cv1 = const > cv2 = (none)으로 cv1은 cv2보다 greater cv-qualification이므로.)
체크 끝. 이 경우 ref는 a에 묶입니다. (reference binding)
const int *p2 = p;
는 앞에서 말씀드렸듯 전혀 다른 문젭니다. 이건 레퍼런스 초기화가 아니라 그냥 포인터 변수 초기화죠. p의 값(a의 주소. 타입 int *)이 qualification conversion을 거쳐 const int *이 되고, 그 값으로 p2를 초기화하는 겁니다.이상 C++17 표준 드래프트를 바탕으로 각 초기화가 어떻게 허용되고 어떻게 금지되는지 설명이 된 것 같군요.
하지만 왜?를 묻는다면 이야기가 조금 달라집니다. C++언어 표준은 마치 프로그램과도 같아서 뭔가를 할 수 있는 절차는 잘 알려주지만, 그 Rationale을 친절히 설명해 주진 않거든요. 그러니 이 아래부터는 제 주관적인 해석입니다.
non-constant lvalue reference에 lvalue를 직접 묶는다는 것은 reference가 대상 lvalue의 alias가 되는 셈입니다. 특히나 레퍼런스만 가지고 원본 lvalue를 덮어쓸 수 있기 때문에 문제가 되는데요. 이런 경우를 생각해보시죠.
위와 같은 이상한 짓을 강제 타입 캐스팅 없이 시도할 수 있다는 것은 뭔가 문제가 있다는 뜻이지요. 저는 바로 이런 경우를 막기 위해서 pref와 같은 reference 초기화를 금지했을 거라고 생각합니다.
정말 감사합니다.
자세한 설명 감사드려요.
어렵고 복잡하군요 껄껄
댓글 달기