[C++] 참조자와 포인터, 함수에서의 벡터 호출
참조자(Reference)
포인터(Pointer)와 같이 변수/상수를 가리키는 방법으로, C에서 없던 C++의 새로운 개념이다.
이번 게시글에선 참조자와 포인터의 비교, 이를 이용한 함수에서 벡터를 인자로 호출할 때의 각 방법에 대해서 다루도록 하겠다.
1. 포인터와 참조자
포인터와 참조자의 차이를 알아보기 위해,
100의 값이 들어있는 int형 변수를 포인터와 참조자 두 방식을 사용해 50으로 바꾸는 코드를 아래에 작성해보았다.
// 포인터
int a = 100;
int* pA = &a;
*pA = 50;
cout << a << " " << *pA << endl;
// 참조자
int b = 100;
int& rB = b;
rB = 50;
cout << b << " " << rB << endl;
output
50 50
50 50
이를 통해 알 수 있는 것은, 참조자는 100이라는 값이 저장되어 있는 메모리에
기존 변수명 b로만 접근하던 것을 rB로도 접근할 수 있다는 것이다.
이러한 방식은 가시적으로 보아도 포인터에 비해서 코드가 훨씬 간결해진다는 것을 알 수 있다.
그러나 참조자를 사용하기 위해선 몇 가지 주의사항을 알아야한다.
- 참조자만 단독으로 정의 불가
- 참조자는 가리키는 변수를 변경할 수 없다
- 참조자의 참조자, 참조자의 포인터, 참조자의 배열은 존재할 수 없다
2. 함수에서 벡터를 인자로 받을 때
참조자와 포인터를 이용해서 main함수에서 선언된 벡터를 인자로 받아,
벡터에 값을 push_back하는 함수들을 코드로 표현해보았다.
#include <iostream>
#include <vector>
using namespace std;
void test1(vector<int> v){ // test1함수 내에서 v 벡터를 생성 후 main함수에서의 vector를 복사한다.
v.push_back(1); // 벡터에 1을 추가하지만, main함수의 vector 벡터의 값은 변하지 않는다.
cout << v.size() << endl; // 3 -> v 벡터의 사이즈를 출력
}
void test2(vector<int>* v){ // main함수의 vector를 포인터를 이용해 인자로 넘기는 방식
v->push_back(2); // main함수에 있는 vector에 2가 추가된다.
}
void test3(vector<int>& v){ // main함수의 vector를 참조자를 이용해 인자로 넘기는 방식
v.push_back(3); // v가 main함수의 vector와 같은 메모리 공간을 가리킨다. -> main함수의 vector에 3이 추가된다.
}
int main(){
vector<int> vector = {0, 0};
test1(vector); // vector 값 추가 x
test2(&vector); // vector 값 추가 o - 포인터
test3(vector); // vector 값 추가 o - 참조자
for (int i : vector){
cout << i << " ";
}
cout << endl;
}
output
3
0 0 2 3
위의 코드와 출력 결과를 확인해보면, 참조자와 포인터의 사용법을 간단히 확인할 수 있다.
정리,
참조자는 C++에서 새로 추가된 변수를 가리키는 방법이다.
참조자는 포인터보다 사용할 때 코드가 간결하나, 참조자 사용 시 주의사항을 생각해서 사용하도록 한다.