일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- for
- 42cursus
- docker
- Class
- 포인터
- iF
- 동적할당
- 패킹
- 2차원배열
- C언어
- python
- ft_server
- C++
- 자료형
- float
- else if
- jupyter 단축키
- 42
- cout
- 구조체
- vs코드 단축키
- nginx
- list
- 42서울
- While
- 함수
- phpmyadmin
- libft
- Double
- 42Seoul
- Today
- Total
Developer
4.(C++) 레퍼런스 (Reference) 본문
레퍼런스(참조자)는 원하는 변수를 또 다른 이름으로 사용할 수 있게해준다. 쉽게 말하면 변수에 별명(Alias)을 정의해줄 수 있다.
자료형 &별명 = 별명을 부여할 대상
레퍼런스의 선언 방법은 위와 같다.주의할 점은 대상의 자료형과 별명의 자료형이 같아야 하며, 별명을 부여받는 대상은 실제 메모리를 점유하고 있는 좌변 값(l-value)이어야 한다. 또한 선언과 동시에 초기화해주어야 한다(초기화가 반드시 필요할 뿐 이후 대상을 변경할 수 있다).
#include<iostream>
using namespace std;
void swap(int x,int y){
int temp=x;
x=y;
y=temp;
}
int main(void){
int a=1,b=5;
swap(a,b);
cout<<"a : "<<a<<endl;
cout<<"b : "<<b<<endl;
return 0;
}
#include<iostream>
using namespace std;
void swap(int *x,int *y){
int temp=*x;
*x=*y;
*y=temp;
}
int main(void){
int a=1,b=5;
swap(&a,&b);
cout<<"a : "<<a<<endl;
cout<<"b : "<<b<<endl;
return 0;
}
코드1과 코드2는 C언어에서 call by vaule와 call by reference를 설명할 때 많이 사용하는 코드이다.
정상적으로 두 변수의 값이 swap되려면 포인터를 사용해 해당 변수의 주소를 보내서 다시 역참조(*)연산자를 사용해 함수를 작성해주어야 한다. 물론 함수를 호출할때 주소를 전달해 주어야하므로 주소 연산자(&)도 작성해주어야한다. 하지만 레퍼런스(참조자)를 사용하면 더 간단하게 사용이 가능하다.
#include<iostream>
using namespace std;
void swap(int &x,int &y){
int temp=x;
x=y;
y=temp;
}
int main(void){
int a=1,b=5;
swap(a,b);
cout<<"a : "<<a<<endl;
cout<<"b : "<<b<<endl;
return 0;
}
함수를 정의할 때 매개 변수를 레퍼런스를 사용해 선언하였다.
swap(a,b); 코드가 실행되면 swap함수의 정의부분으로 올라가 int &x=a, int &y=b; 가 실행되어 x와 y는 a와 b의 별명이 된다. 따라서 다른 연산자를 추가로 사용하지 않고 swap함수에서 main 함수에 있는 변수를 변경할 수 있는것이다.
이러한 레퍼런스에 사용에는 여러 장점이 있다. 함수를 호출할 때 주소 연산자를 사용하지 않아도 되고, 함수의 내용에서 역참조 연산자를 사용하지 않아도 된다. 만약 구조체를 전달한다면 ->연산자가 아닌 .연산자로 읽을 수 있다.
레퍼런스 주의점
1.레퍼런스에 대한 레퍼런스는 선언할 수 없다.(&&연산자 에러)
->레퍼런스로 다른 레퍼런스를 대상으로 한다면 결국 하나의 대상에 3개의 이름이 생기는 것이다.
2.레퍼런스에 대한 포인터는 선언할 수 없다.(&*연산자는 에러 ,포인터에 대한 레퍼런스는 가능)
3.레퍼런스의 배열은 선언할 수 없다.(배열의 레퍼런스는 가능)
레퍼런스와 포인터
레퍼런스의 사용법을 보면 포인터와 유사한 것을 알 수 있다. 사실 틀린말은 아니다. 실제 컴파일러는 레퍼런스를 포인터로 바꾸어 컴파일한다.
swap 함수를 예로 살펴보자.
void swap(int &x,int &y){
int temp=x;
x=y;
y=temp;
}
위의 코드를 컴파일러는 아래의 코드로 바꾸어 컴파일한다.
void swap(int *x,int *y){
int temp=*x;
*x=*y;
*x=temp;
}
물론 함수를 호출하는 코드도 swap(&a,&b)로 바뀐다.
레퍼런스와 상수
조금만 생각해보면 상수에 대한 레퍼런스는 필요 없다는 것을 알 수 있다. 상수는 좌변 값(l-value)가 아니므로 레퍼런스를 만들 수 없다. 하지만 레퍼런스를 선언할 때 const를 작성해주면 상수 레퍼런스를 만들 수 있다.
int &a=123; //에러 const int &a=123 //정상작동 const int a=123 //위의 상수 레퍼런스와 같음
위의 코드들을 보면 결국 상수 레퍼런스를 만들던 그냥 상수 변수를 만들던 똑같은 의미이므로 실용성이 없다.
'Programming Language > C++' 카테고리의 다른 글
6.(C++) 구조체 (0) | 2020.08.01 |
---|---|
5.(C++) 함수 (0) | 2020.08.01 |
3.(C++) 제어문 (0) | 2020.08.01 |
2.(C++) 입출력 및 자료형 (0) | 2020.08.01 |
1.(C++) Hello World! (0) | 2020.08.01 |