일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 파이썬
- 스프링
- 백준 알고리즘
- java
- python
- 1과목
- softeer
- C++
- 시나공
- 프로그래머스
- 백준알고리즘
- CJ UNIT
- 회고
- 문제풀이
- programmers
- 자바
- MYSQL
- 백준
- SW봉사
- 공부일지
- 정보처리산업기사
- SQL
- 코딩봉사
- kotlin
- 코딩교육봉사
- 알고리즘
- BFS
- 코틀린
- 소프티어
- 데이터베이스
- Today
- Total
JIE0025
[C++] 참조자 (&) 본문
일단 변수란 무엇인가.
변수 : “할당된 메모리공간에 붙여진 이름”
우리는 변수의 이름을 통해 변수에 할당된 메모리 공간에 접근한다.
참조자(&)
참조자는 하나의 메모리 공간에 2개 이상의 이름을 부여하기 위해 생겨난 개념이다.
회사에서 홍길동이 있는데 외국계 회사라 고유 닉네임이 있고, 홍길동의 닉네임은 RED라고 가정해보자.
홍길동님 이거 오늘까지 마무리해주세요~
RED님 이거 오늘까지 마무리해주세요~
해도 고유 닉네임이기 때문에 의사소통엔 문제가 없다.
참조자의 선언
참조자로 사용하고 싶은 변수명 앞에 &기호를 붙혀주면된다.
int num = 5;
int &n1 = num;
참조자의 특징
- 참조자의 수에는 제한이 없다.
- 참조자의 참조자를 선언할 수도 있다. >> int& n2 = n1;
- 참조자는 변수에 대해서만 선언이 가능하며, 선언과 동시에 변수를 참조해야한다.
참조자 사용
#include<iostream>
using namespace std;
int main(){
int arr[3] = {1,2};
int &r1 = arr[0];
int &r2 = arr[1];
cout << r1 << endl;
cout << r2 << endl;
return 0;
}
참조자 함수
call-by-reference 란 주소 값을 전달받아 함수 외부에 선언된 변수에 접근하는 형태의 함수 호출을 의미한다.
참조자의 개념을 배운 이시점에서
call-by-reference는 두가지로 구분될 수 있다.
- 주소값을 이용
- 참조자를 이용
참조자를 이용한 call by reference
- 참조자는 선언과 동시에 변수로 초기화 되어야 하지만.
- 함수에 매개변수로서 선언될땐, 함수 호출시 전달되는 인자로 초기화가 된다.
>> 매개변수 자체가 함수가 호출될 때 초기화가 진행되므로 참조자를 매개변수로 선언할 수 있다.
void swap(int &r1, int &r2){
int tmp = r1;
r1 = r2
r2 = tmp;
}
참조자는 닉네임과 같으므로
주소값을 이용한 call-by-reference처럼 *같은 기호를 따로 붙혀서 접근하지 않는다.
위의 swap 함수를 호출할 때
swap(a,b); 이런식으로 변수를 인자로 전달하면 괜찮지만
상수값을 전달하는 아래 같은 경우는 컴파일에러가 뜬다. 이는 인자값이 상수라서 공간이 사라지기 때문이다.
swap(3,5);
아래는 포인터변수를 swap하되, 매개변수로 참조자를 사용한 예시이다.
int main(){
int n1 = 3;
int *p1 = &n1;
int n2 = 5;
int *p2 = &n2;
swap(p1, p2);
}
void swapPtr( int * (&prf1) , int * (&prf2)){
int * ptr = prf1;
prf1 = prf2;
prf2 = ptr;
}
반환형이 참조형(&) 인 경우?
: 반환 값을 무엇으로 저장하느냐에 따라 결과가 차이가 있다.
이렇게 얘기하면 이해가 잘 안되니 예시를 봐야한다.
#include<iostream>
using namespace std;
int& test(int &ref){
ref ++
return ref
}
int main(){
int one = 1;
int &two = test(one);
one ++;
two ++;
cout << one << endl;
cout << two << endl;
return 0;
}
위 코드를 해석해보자.
- one이라는 변수공간이 있는데 1이 할당되어 있다.
- test 매개변수는 &ref이기 때문에 one의 별명으로써 ref를 사용할 수 있게 되었다.
- ref++ 는 one의 값을 1 증가시킨다. (2)
- return ref는 &two 로 반환되면서 one의 별명으로써 two가 생겼다. > 함수의 생명주기가 끝나면서 ref라는 별명은 사라진다.
- one 의 값을 1 증가시키고 (3)
- 별명 two를 사용해서 one의 값을 1 증가시키면 (4)
- one을 출력하면 >> 4
- two를 출력하면 >> 4
이번엔 return 이후에 그냥 int two 로 할당되는 경우를 봐보자.
#include<iostream>
using namespace std;
int& test(int &ref){
ref ++
return ref
}
int main(){
int one = 1;
int two = test(one);
one ++;
two += 100;
cout << one << endl;
cout << two << endl;
return 0;
}
이 경우엔 반환 이후에 two라는 새로운 변수가 생겼다.
one과 two는 서로 다른 메모리공간에 존재한다는걸 먼저 알고 해석해보자.
- one엔 1이있다.
- test(one)을 통해 one에는 ref라는 별명이 생기고
- res ++ 을 해서 one의 값은 2가된다. ref는 별명이기 때문에 여기에서 ref를 출력해도 2가 나온다.
- return ref를 했을 때 ref의 값은 2이고 이 값이 two로 할당된다. 그러나 two는 one과는 독립적이기 때문에 ref를 통해 갈 수 있는 값만 전달된다. 이후 ref는 함수의 종료로 소멸된다.
- one에는 2, two에는 2가 있는 상황에서
one ++;
two += 100; 을 하게 되면
one (3)
two ( 102) 가 출력되는 것을 확인할 수 있다.
반환값을 int & two 에 저장하느냐, int two 에 저장하느냐에 따라 결과는 달라진다.
>> 첫번째 경우
int one =1;
int &ref = one;
int &two = ref;
>> 두번째 경우
int one =1;
int &ref = one;
int two = ref;
const 참조자
참조자를 통해 값을 변경하지 않을려면 앞에 const 키워드를 사용하면 된다.
const int& num = n;
🚫 논리적 오류 🚫
아래 경우를 C++ 에서 돌리게 되면 오류가 난다.
const int num1;
int & ref = num1;
ref = 3;
상수화된 변수 num1은 어떤 경로를 통해서도 값이 변경되면 안되는데 참조자를 통해 바꾸려고 한다는 점...
이부분은 C++에서 허용하지 않기 떄문에
참조자를 선언하고 싶다면 const참조자를 사용해야한다.
const int num1;
const int & ref = num1;
const 참조자를 이용한 상수 참조가 가능하다 ?
원래 참조자엔 변수를 할당해야만한다.
그러나 const 키워드를 이용한 참조자에는 상수 참조가 가능하다.
임시 변수라는 걸 만들어 이 공간에 상수를 저장하고 참조자가 이를 참조할 수 있다.
const int& ref= 1;
이건 왜 만들어졌을까?
함수의 매개변수로 참조자가 있다고 해보자.
굳이 바뀌지 않을 어떤 상수 값을 전달하는 경우엔 인자값을 전달해주기 위해 변수를 생성해야만 하면 공간낭비가 일어난다.
이럴때 매개변수에 const int & 를 사용하면 된다.
#include<iostream>
using namespace std;
int add(const int & num1, const int & num2){
return num1 + num2
}
int main(){
cout << add(3,4) << endl;
}
'기타 학습 > Language' 카테고리의 다른 글
[C++] 구조체 (0) | 2022.05.10 |
---|---|
[C++] 동적할당 new , 소멸 delete (0) | 2022.05.10 |
[C++] C언어 기본 복습 (const , 메모리공간, malloc, free, call-by-value, call-by-reference ) (0) | 2022.05.06 |
[C++] 이름공간 (namespace), 범위지정 연산자의 사용 (0) | 2022.05.06 |
[C++] 매개변수 디폴트 값 (default vaule) (0) | 2022.05.06 |