[전문가를 위한 C++] 11장. C++의 까다롭고 유별난 부분
Chapter 11. C++의 까다롭고 유별난 부분
11.1 레퍼런스
- 레퍼런스 변수
- 레퍼런스 변수는 반드시 생성과 동시에 초기화 되야 한다.
int x = 3; int &ref = x;
- 아래와 같이 레퍼런스 변수를 클래스 밖에서 선언만 하고 초기화 하지 않으면 컴파일 에러가 발생한다.
int &emptyRef; // compile error
- 정수 리터럴처럼 이름 없는 값에 대해서는 레퍼런스를 생성할 수 없다. 단, const 레퍼런스는 얼마든지 만들 수 있다.
int &unnameRef1 = 5; // compile error const int &unnameRef2 = 5; // OK
- 임시객체도 마찬가지로 non-const 레퍼런스는 만들 수 없지만, const 레퍼런스는 만들 수 있다.
std::string getString() { return "Hello World!" } std::string &string1 = getString(); // compile error const std::string &string2 = getString(); // OK
- (1) 레퍼런스 대상 변경하기
- 레퍼런스는 처음 초기화 할 때 지정한 변수만 가리킨다. 레퍼런스는 한 번 생성되고 나면 가리키는 대상을 변경할 수 없다.
- 한 번 선언된 레퍼런스에 다른 변수를 대입하면 레퍼런스 대상이 바뀌는 것이 아니라 원래 가리키던 변수의 값이 새로 대입한 변수의 값으로 바뀐다.
int x = 3, y = 4; int& xRef = x; xRef = y; // xRef가 y를 가리키는 것이 아니라, x의 값을 4로 변경한다.
- xRef에 y의 주소를 대입하면 가리키는 대상을 바꿀 수 있을까?
xRef = &y; // compile error. y의 주소는 포인터이고, xRef는 int의 레퍼런스이다.
- 레퍼런스에 레퍼런스를 대입하면 가리키는 대상을 바꿀 수 있을까?
int x = 3, y = 5; int &xRef = x; int &yRef = y; yRef = xRef; // yRef가 가리키는 대상은 바뀌지 않고, y의 값이 3으로 변경된다.
- 결론 : 레퍼런스를 초기화 하고 나면 레퍼런스가 가리키는 변수를 변경할 수 없고, 그 변수의 값만 바꿀 수 있다.
- (2) 포인터에 대한 레퍼런스와 레퍼런스에 대한 포인터
- 레퍼런스는 모든 타입에 대해 만들 수 있다. 심지어 포인터 타입을 가리키는 레퍼런스도 만들 수 있다.
int *intP; int *&ptrRef = intP; ptrRef = new int; *ptrRef = 5; // ptrRef를 변경하면 intP가 바뀐다.
- 레퍼런스가 가져온 주소는 그 레퍼런스가 가리키는 변수의 주소와 같다.
int x = 3; int &xRef = x; int *xPtr = &xRef; // 레퍼런스의 주소는 값에 대한 포인터와 같다. x에 대한 레퍼런스 주소를 가져와서 xPtr가 x를 가리키도록 설정한다. *xPtr = 100;
- 레퍼런스에 대한 레퍼런스는 선언할 수 없다. 즉, int &&나 int&*와 같이 선언할 수 없다.
- 레퍼런스는 모든 타입에 대해 만들 수 있다. 심지어 포인터 타입을 가리키는 레퍼런스도 만들 수 있다.
- 레퍼런스 변수는 반드시 생성과 동시에 초기화 되야 한다.
- 레퍼런스 데이터 멤버
- 레퍼런스는 어떤 변수를 가리키지 않고서는 존재할 수 없다. 따라서 레퍼런스 데이터 멤버는 반드시 생성자의 본문이 아닌 생성자 이니셜라이저에서 초기화 해야 한다.
class MyClass { public: MyClass(int &Ref) : mRef(Ref) { } private: int &mRef; };
- 레퍼런스는 어떤 변수를 가리키지 않고서는 존재할 수 없다. 따라서 레퍼런스 데이터 멤버는 반드시 생성자의 본문이 아닌 생성자 이니셜라이저에서 초기화 해야 한다.
- 레퍼런스 매개변수
- const 레퍼런스
- 레퍼런스는 기본적으로 const 속성을 가지고 있다. 다시 말해, 가리키는 대상이 절대 변하지 않는다. 그래서 명시적으로 const지정을 할 필요가 없다.
- 레퍼런스에 대한 레퍼런스를 만들 수 없기 때문에 참조는 단 한 단계 뿐이다. 여러 단계로 참조하는 유일한 경우는 포인터에 대한 레퍼런스를 만들 때 뿐이다.
int z; const int& zRef = z; zRef = 4; // compile error
- const 레퍼런스
11.2 키워드 혼동
- constexpr 키워드
- constexpr 키워드를 사용하면 상수 표현식으로 다시 정의될 수 있다.
11.3 타입과 캐스팅
- const_cast()
- static_cast()
- reinterpret_cast()
- dynamic_cast()