(전체가 아니라 C#과 차이가 있는 부분을 중심으로 요약 정리)

레퍼런스

C++에서 레퍼런스란 일종의 변수에 대한 앨리어스(alias, 별칭)이다. 레퍼런스를 이용해서 수정한 내용은 그 레퍼런스가 가리키는 변수의 값에 그대로 반영된다. 레퍼런스는 변수의 주소를 가져오거나 변수에 대한 역참조 연산을 수행하는 작업을 자동으로 처리해주는 특수한 포인터라고 볼 수 있다. 또는 변수에 대한 다른 이름(별칭)이라 생각해도 된다.

변수를 레퍼런스로 만들 수 있고, 클래스의 데이터 멤버를 레퍼런스로 만들 수 있고 함수나 메서드가 레퍼런스를 매개변수로 받거나 레퍼런스를 리턴하게 만들 수 있다.

레퍼런스 변수

레퍼런스 변수는 반드시 생성하자마자 초기화 해야 한다.

int x = 3;
int& xRef = x;

x 변수에 대한 대입문 바로 뒤에 나온 xRef는 x에 대한 또 다른 이름이다. xRef를 사용하는 것은 x를 사용하는 것과 같다. xRef에 어떤 값을 대입하면 x의 값도 바뀐다.

정수 리터럴처럼 이름 없는 값에 대해서는 레퍼런스를 생성할 수 없다. 단 const 값에 대해서는 레퍼런스를 생성할 수 있다.

int& unnamedRef1 = 5;  // 컴파일 에러 발생
const int& unnamedRef2 = 5;  // 정상 작동

임시 객체도 마찬가지인데, 임시 객체에 대해 non-const 레퍼런스는 만들 수 있지만 const 레퍼런스는 얼마든지 만들 수 있다. 예컨대 다음과 같이 std::string 객체를 리턴하는 함수를 살펴보자.

std::string getString() { return "Hello world!"; }

getString()을 호출한 결과를 const 레퍼런스에 담을 수 있다. 그러면 이 레퍼런스가 스코프를 벗어나기 전까지 std::string 객체를 계속 가리킬 수 있다.

std::string& string1 = getString();  // 컴파일 에러 발생
const std::string& string2 = getString();  // 정상 작동

레퍼런스 대상 변경하기

레퍼런스는 처음 초기화할 때 지정한 변수만 가리킨다. 레퍼런스는 한 번 생성되고 나면 가리키는 대상을 바꿀 수 없다.

이 규칙 때문에 문법이 좀 헷갈리는데 레퍼런스를 선언할 때 어떤 변수를 ‘대입’ 하면 레퍼런스는 그 변수를 가리킨다. 하지만 이렇게 한 번 선언된 레퍼런스에 다른 변수를 대입하면 레퍼런스가 가리키는 대상이 바뀌는 것이 아니라 레퍼런스가 원래 가리키던 변수의 값이 새로 대입한 변수의 값으로 바뀌게 된다.

int x = 3, y = 4;
int& xRef = x;
xRef = y;  //xRef가 y를 가리키는 것이 아니라 x의 값을 4로 변경한다.

여기서 y의 주소를 대입하면 가리키는 대상을 바꿀 수 있다고 생각할 수 있다.

xRef = &y;  // 컴파일 에러 발생