본문 바로가기

PL/C & C++

[C++] 참조형 변수 : &

References vs pointers

참조형과 포인터는 흥미로운 관계에 있다. 참조형은 접근할 때 암시적으로 역참조되는 포인터와 같은 역할을 한다. (참조형은 내부적으로 포인터를 사용하여 컴파일러서 구현된다.)

A brief review of l-values and r-values

'01.02 - 변수, 초기화 및 할당' 포스트에서 l-value와 r-value를 공부한 적이 있다.
요약하면, l-value는 메모리 주소를 가진 객체이고 r-value는 메모리 주소가 없고, 표현식 범위에만 있는 임시 값이다.

 

참조형 변수 (Reference variable)

지금까지 두 가지 변수 타입을 공부했다.

  • 일반 변수(normal variable): 직접 값을 보유.
  • 포인터(pointer): 다른 값의 주소(또는 null)를 보유.

참조형(reference)은 C++에서 지원하는 세 번째 변수 타입이다. 참조형은 다른 객체 또는 값의 별칭으로 사용되는 C++ 타입이다.

C++은 세 가지 종류의 참조형을 지원한다.

  1. non-const 값 참조형
  2. const 값 참조형
  3. r-value 참조형

 

 

C++ 07.15 - 참조형 변수 (Reference variable)

참조형 변수 (Reference variable) 지금까지 두 가지 변수 타입을 공부했다. 일반 변수(normal variable): 직접 값을 보유. 포인터(pointer): 다른 값의 주소(또는 null)를 보유. 참조형(reference)은 C++에서 지..

boycoding.tistory.com


완벽한 전달

완벽한 전달은 오버로드된 함수의 필요성을 줄이고 전달 문제를 방지하는 데 도움이 됩니다. 전달 문제 는 참조를 매개 변수로 사용 하는 제네릭 함수를 작성 하 고 이러한 매개 변수를 다른 함수에 전달 하거나 전달 하는 경우에 발생할 수 있습니다. 예를 들어 제네릭 함수가 const T& 형식의 매개 변수를 사용하는 경우 호출된 함수는 해당 매개 변수의 값을 수정할 수 없습니다. 제네릭 함수가 T& 형식의 매개 변수를 사용하는 경우에는 rvalue(예: 임시 개체 또는 정수 리터럴)를 사용하여 해당 함수를 호출할 수 없습니다.

 

 

일반적으로 이 문제를 해결하려면 각 매개 변수에 대해 T&  const T&를 둘 다 사용하는 제네릭 함수의 오버로드된 버전을 제공해야 합니다. 따라서 오버로드된 함수의 수가 매개 변수의 수와 함께 급격하게 증가합니다. rvalue 참조를 사용하면 마치 다른 함수가 직접 호출된 것처럼 임의의 인수를 받아들여 다른 함수에 전달하는 함수의 버전을 작성할 수 있습니다.

 

W, X, Y  Z의 4가지 형식을 선언하는 다음 예제를 살펴보십시오. 각 형식에 대 한 생성자는 const 및 비 lvalue 참조의 다른 조합을 매개 변수로 사용 const 합니다.

 

 

 

 

Rvalue 참조 선언 자: &&

다음에 대해 자세히 알아보세요. Rvalue 참조 선언 자: &&

docs.microsoft.com


선언(declare)에서의 *와 &는 표현(expression)에서의 *와 &와 아무 상관없다는 걸 아무도 안가르쳐줬었다..

 

(1) 참조 &

이퀄 연산자 왼쪽에 있는 &, 즉 변수 타입을 선언하는데 사용된 &는, 왼쪽의 변수가 오른쪽의 값을 부르는 또 다른 이름이라는 뜻이 된다.

즉, “같은 사람을 부르는 여러 별명 중 하나”로 동작한다.

 

 

 

(2) 주소 &

이퀄 연산자 오른쪽에 있는 &, 또는 이미 선언된 변수나 값에 대한 연산자로 쓰는 &는, 값이 위치한 주소를 까준다.

 

(3) 함수 입력에 선언된 참조 &

함수 입력에 있는 &는 입력값의 복제본이 아니라 원본을 받겠다는 뜻이다. C#의 ref나 out 키워드에 대응된다. 즉, 함수 내부에서 입력된 값에 적용한 변경사항이 함수 외부에서도 그대로 적용된다.

처음부터 타입으로서의 &로 이해하면 이해 잘안된다. 물론, 사실 이 동작은 (1)의 연장선이다. 함수에 입력된 값의 복제본이 아닌, 입력한 값을 가리키는 또다른 별명을 만들어 함수 내부에서 쓰겠다는 이야기다.

 

 

(4) 포인터 *
이퀄 연산자 왼쪽에 있는 *는, 즉 변수 타입을 선언하는데 사용된 *는 그냥 주소 저장하는 타입이다.

포인터는 친구의 집 주소다. 참조는 친구를 부르는 별명 중 하나다.

참조의 값을 수정하면, 실체가 수정된다. 포인터 타입의 변수는, 그 값을 수정 한다고 실체가 수정되지 않는다. 포인터 타입의 변수가 가르키는 곳에 도착해서 값을 수정해야 실체가 수정된다.

주소를 메모한 종이에 뭘 한다고, 실제로 무슨 일이 일어나는게 아니다. 주소를 메모한 종이를 통해 실제 그 주소로 이동해야 실체를 만나고, 무언가를 수정할 수 있다.

 

 

 

(5) 역참조 *

선언용* 가 주소를 받는 변수 타입(포인터 타입)을 선언하는데 사용되는 반면에, 이미 선언된 변수에 사용되는* 연산자는, 해당 주소로 이동하는 연산자다. 쇼트 컷 버전으로 ->를 쓰기도함.

 

 

 

 

 

C++ 포인터/참조 연산자는 쪼개서 이해해야 쉽다. – I_Jemin

나는 처음 학교에서 C++ 배울때 선언(declare)에서의 *와 &는 표현(expression)에서의 *와 &와 아무 상관없다는 걸 아무도 안가르쳐줬었다.. C++ 참조와 포인터를 어려워 하는 이유는, 연산자들의 모습만

ijemin.com

 

'PL > C & C++' 카테고리의 다른 글

[C++] 깊은 복사 , 얕은 복사  (0) 2021.03.05
[C++] Rvalue 참조 선언자: &&  (0) 2021.03.04
[C++] 멤버 이니셜라이저  (0) 2021.03.04
[C++] char to int  (0) 2021.03.04
[C++] vector 탐색  (0) 2021.03.01