C++에서 상수 문자열을 참조자가 참조할 수 있게 하는 방법
글쓴이: 익명 사용자 / 작성시간: 목, 2017/07/13 - 4:46오후
원래 참조자가 참조할 수 있는 대상은 변수로 한정되긴 하나 const를 붙여줌으로써 상수를 참조 대상으로 확장시킬 수 있잖아요?
그래서 문자열은 첫번째 문자값에 대한 주소가 반환되니까
const char * (&ref_str) = "Hello reference";
//이렇게 선언하니까 컴파일 에러가 발생하더군요. 왜 이 선언은 사용할 수 없는 형태인지 모르겠습니다.
두번째로 생각해낸 것이
const char (&ref_str)[] = "Hello refernece";
//두 번째 형태는 컴파일 에러 없이 출력도 잘 됩니다.
제가 생각하기에는 두 개의 선언방식 모두 동일한 의미를 뜻하니까 무엇을 사용하든 무관할 것 같은데..무엇이 문제인지 알고 싶네요.
Forums:
아주 약간 첨언...
1. "Hello reference"의 type은 "array of 16 const char" 입니다. NUL문자는 빠트리기 쉽지요.
2. string literal을 곧바로 reference에 묶어 버리면 Array-to-pointer conversion을 피할 수 있습니다. 그러면 C++11의 rvalue reference 없이도 레퍼런스에 담을 수 있겠지요. (ref_str4 참조)
3. C++03에는 rvalue reference가 없지만, 때로는 reference가 오른값에 묶일 수 있습니다. 바로 많이들 사용하셨을 상수 참조자 용법입니다. C++11 이후로 이런 변칙적인 문법은 서서히 잊혀져 갈지도 모르겠네요. (ref_str5 참조)
4. 제 컴파일러로는 왜 ref_str2 선언이 컴파일이 안 될까요. 질문자님은 된다고 하셨는데 말이죠. 저는 g++ 4.8.5를 썼고 -std=c++03 -pedantic -pedantic-errors 옵션을 주었습니다.
흠.
흠.
찾아보니 g++ 4.9.2까지는 컴파일이 안 되고 g++ 4.9.3부터 컴파일이 되는군요.
옵션은 모두 -std=c++03 -pedantic -pedantic-errors
3. 제가 lvalue와 rvalue의 개념을
3. 제가 lvalue와 rvalue의 개념을 혼동해서인지 이해가 안되는 부분이 있습니다.
const char *(&ref_str) -> lvalue reference까지 이해가 됩니다.
lvalue reference는 lvalue에만 한정되어 참조자 역할을 한다는 것이 결국 저는 이렇게 받아들여지네요.
원래 참조자라는 것이 lvalue 값에만 한정되어 사용되는 것이 원칙입니다.
제가 언급한 예시처럼 가장 흔한 rvalue로 상수를 말할 수 있겠네요. 상수를 참조해버리면 참조자를 통해 접근뿐만 아니라 값의 변경도 가능해야 하는데 rvalue는 해당 연산식(?)이 끝나버리면 재참조할 수 있는 값의 속성이 아니기 때문이죠..
그래서 이걸 야매..라고 해야할지는 모르겠지만 억지로 방법을 생각해냅니다.
const 키워드를 사용하는거죠. const 키워드를 사용함으로써 참조자에게 속성을 붙여줍니다.
참조자가 참조하는 대상이 상수이므로 참조자를 통한 값 변경을 금해버리는 것이죠.
그래서 const int &ref_integer = 100; //error 발생하지 않음
만일 제가 char * (&ref_str) 이렇게 선언했다면 답변해주신분의 말씀이 맞습니다. 하지만 그러한 에러 발생을 피하기 위해 const char *(&ref_str)을 선언한 것이고요.
즉 const 키워드가 lvalue reference의 값에 rvalue가 들어갈 수 있게 해주는 것이죠.
제가 질문의 요점을 잘못 잡았군요.
제가 질문의 요점을 잘못 잡았군요.
C++03에서 일반적으로 참조자는 lvalue에 묶입니다. 사실 그냥 "변수로 한정"된다고만 말하기에는 조금 미묘합니다:
상수 타입을 가리키는 참조자는, 말씀하신 대로 rvalue에 묶일 수 있습니다.
제가 이미 말씀드렸다시피 다소 변칙적인 문법인데, C++ 표준에 이런 용법을 정당화하는 항목이 따로 있어요. 자세한 설명은 생략하도록 하죠.
제가 상수 타입을 가리키는 참조자라고 말씀드린 점 주목하세요.
다른 때는 문제가 안 되는데 포인터에서 문제가 됩니다.
포인터 선언에서의
const
의 용법은 기초 C++ 선언 문법 중에서 가장 혼란스러운 문법 중 하나거든요.결론부터 말씀드리면, 포인터 자체가 상수인 경우, 포인터가 가리키는 대상이 상수인 경우로 나누어 생각해야 합니다.
코드로 보여드리죠:
Scott Meyers의 책 『Effective C++ 3판』 항목 3에서 위 내용을 간단히 요약해서 설명합니다.
질문자님의 예제로 돌아가 봅시다.
string literal
"hello"
는const char [6]
타입 lvalue입니다.const char
, 즉 상수형 문자가 여섯 개 있는 배열이라는 거죠.array-to-pointer 변환에 의해 위 표현식은
const char *
타입 rvalue로 변환됩니다.위에서 포인터 선언에
const
가 어느 자리에 들어갈 때 어떤 의미를 갖는지 말씀드렸던 것을 다시 살펴보세요.const char *
는 상수형 문자(const char
)를 가리키는 비상수 포인터입니다!다시 말해서,
const char *
에서const
의 의미는포인터가 상수라는 게 아니라, 가리키고 있는 문자가 상수라는 것입니다.
string literal을 이루는 문자는 변경 불가능하다는 제약으로부터 온 것이지요.
상수 타입을 가리키는 참조자를 만들기 위해서는, 포인터 자체가 상수여야 합니다. 물론 이 경우에는 포인터가 가리키고 있는 (string literal의) 문자들 역시 상수입니다. 그래서 제가 위 답변의 3.에서 보여드린 선언이 나온 것입니다.
확인이 늦어져서 죄송합니다;; 일단 답변 정말
확인이 늦어져서 죄송합니다;; 일단 답변 정말 감사합니다.
제가 아직 많이 부족해서 지금 당장 답변해주신 내용이 완전하게 이해된다고는 할 수 없으나 제가 이해한 것과 남은 의문점에 대해 말씀드릴게요.
일단 일반적으로 const를 사용하는 경우와 포인터 선언에서 const를 사용하는 경우를 조금 달리 생각해야 한다는 것 같네요. 뭐..한국말로 번역했을 때 괜히 더 복잡해지니까 그냥 영어로 명칭을 설명하자면 const 키워들 맨앞에 두느냐 아니면 변수명 앞에 두느냐에 따라 pointer to constant, constant pointer 이렇게 구분되는 거 맞습니다.
그런데 C언어와 다르게 C++은 참조자라는 개념이 나오죠. 참조자는 음..포인터도 아닌 그냥 선언된 변수에 대한 별칭..쉽게 말해 대타 이런 것 같네요.
현재 저는 상수 문자열에 대한 참조자를 선언하고 싶은 것이고요.
여기서 일단 참조자는 조금 있다가 살펴보고 문제를 축약해서 상수 문자열을 가리키는 포인터를 선언한다고 합시다. 그렇다면 저는 char형 변수 포인터 하나를 선언할 것입니다. 그런데 변수포인터가 상수문자열을 가리켜야 한다는 것입니다. 그래서 변수 포인터보고 상수 문자열을 가리킬 포인터가 되어줘라고 하기 위해 선언 맨 앞에 const를 붙여줍니다.
그런데 여기서 상수 문자열을 가리킬 것이라해서 포인터를 상수화시키지는 않았습니다. 그럴 이유가 없습니다. 그렇다면 이제 본 문제로 돌아가보면.. 제가 앞앞에서 참조자에 대해 말씀드릴 때 포인터가 아니고 그냥 대타라고 표현했습니다.
어떤 타입으로 선언된 변수이든 참조자는 해당 변수를 대신해서 쓸 수 있는 개념이라고 알고 있습니다.
그렇다면 참조자가 참조할 대상이 포인터이긴한데 그게 constant pointer일 필요가 있을까요?
요점만 말씀드리자면 참조자가 참조할 대상이 상수문자열에 대한 주소여서 pointer to constant type이어야겠네요. constant pointer tpye이 아니라 pointer to constant의 속성을 가지기만 하면 되는데 참조자의 참조 타입이 constant pointer type이어야 한다는 부분이 뭔가.. 제 머리로는 명쾌히 받아들이질 못하는 것 같습니다..
Visual Studio 로 디버깅해보시면.
어셈블리 소스 코드로 보입니다. 그거도 참고 해보 세요.
----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
댓글 달기