이 포스팅은 Object Oriented Programming 시리즈 23 편 중 6 번째 글 입니다.

  • Part 1 - 01: Introduction
  • Part 2 - 02: Identifier, Variable, constant, Std IO, Operator
  • Part 3 - 03: Functions #1 - Calling (호출)
  • Part 4 - 04: Functions #2 - Local, Global Variable
  • Part 5 - 05: Functions #3 - Recursion Function, Reference Variable (재귀함수)
  • Part 6 - This Post
  • Part 7 - 07: Functions #5 - CallbyValue, CallbyReference
  • Part 8 - 08: Selection and Repetition
  • Part 9 - 09: File Input & Output (파일입출력)
  • Part 10 - 10: String library, rand(), srand()
  • Part 11 - 11: Pointer, Function Pointer
  • Part 12 - 12: Array, Vector (정적배열, 동적배열)
  • Part 13 - 13: class, object
  • Part 14 - 14: this, operator overloading
  • Part 15 - 15: friend, static, destructor
  • Part 16 - 16: Inherence (상속)
  • Part 17 - 17: Static Binding, Dynamic Binding, Header File
  • Part 18 - 18: Generic Programming, Template
  • Part 19 - 19: List Container
  • Part 20 - 20: Iterator (반복자)
  • Part 21 - 21: algorithm Library
  • Part 22 - 21: functional, lambda function
  • Part 23 - 22: Exception handling
▼ 목록 보기

참조변수는 내가 선언한 값을 동시에 가리킨다는 점에서 포인터와 유사한 측면이 있다. 또 헷갈리는 점이 있다. C에서 &의 사용은, 내가 저장한 변수의 주소값을 불러오는 용도로 사용했었다. 그런데 C++에 와서는 이 녀석을 참조변수로 사용할 수 있다고 하니 여간 혼돈스러운게 아니다.

Diffrence between Pointer & Reference Variable

C에서 포인터는 장단점이 아주 명확하다.

  • 장점
    • 메모리에 직접적으로 접근할 수 있다.
  • 단점
    • 그렇기 때문에 사용자의 선택이 지배적이다. 즉, 아무렇게나 접근하여 잘못된 주소로 접근할 수 있다는 위험성이 있다.

포인터의 문제점은 선언과 할당을 나누기 때문에 발생한다.

#include <stdio.h>

int main(){
    int x;
    int *a;
    x = 4;
    *a = x;

    return 0;
}

위와 같은 방식으로 선언과 할당을 해준다.

스크린샷 2019-03-19 오전 10 23 01메모리와 할당을 나타내는 그림

이런식으로 가리키게 된다. 그런데 만약 내가 이것보다 복잡한 구조에 포인터를 잘못사용한다면 NULL 또는 Garbage 값이 들어갈 위험이 있다 이런 단점을 보안하는 방식으로 참조변수 가 만들어졌다.

#include <iostream>

int main(){
    int x = 4;
    int &r = x;

    return 0;
}

이렇게 사용할 경우 r은 x를 가리키는 또다른 별칭이 된다. 스크린샷 2019-03-19 오전 10 28 14alias

이런식으로 구성된다. 참조변수는 포인터와 다르게 선언과 할당이 분리되어서 사용되지 않고, 동시에 이루어져야 한다. 즉, 선언과 초기화가 동시에 이루어진다. 그렇기 때문에 포인터에서 발생하는 잘못된 객체를 가리키는 문제점이 해결된다.

Summary

Pointer

  • 선언과 할당이 분리되어 이루어짐
  • 자유롭게 객체를 가리킬 수 있으나, 그렇기 때문에 오류 발생확률이 높음 (Null 값)
  • 선언과 할당이 분리되니, 포인터 변수안의 주소값을 바꿀 수 있음
  • 포인터 변수안에는 해당 객체의 주소값이 들어가있음
  • * 를 사용해서 선언하고 사용함

Reference Variable

  • 선언과 할당이 동시에 이루어짐
  • 그렇기 때문에 포인터에 비해 오류가 날 확률이 줄어듦
  • 또한 선언과 할당이후 다른 객체를 가리킬 수 없음
  • 참조변수는 x 값 자체를 가리킴
  • x 의 별칭이라고 생각하면 됨
  • & 을 사용해서 선언하고 사용함

주소를 가져오는 & 와 참조변수의 &

C 에서 scanf() 같은 함수를 사용할 때, &a 와 같은 방식으로 입력을 받았다. 이 때, &는 변수의 주소를 가져오는 방법으로 생각하고 사용했었다. 같은 &를 쓰면서 왜 하나는 주소를 가져오는 방법으로, 또 참조변수라고 다르게 얘기하는 걸까? 사용법은 2가지가 있는데, 구체적으로 알아보면 굉장히 간단함을 알 수 있다. 차례차례 알아보자.

주소를 가져오는 &

#include <stdio.h>

int main(){
   int x;
   int *a;

   a = &x;

   return 0;
}

이 코드를 보면, ax 의 주소를 받음을 알 수 있다. 이때 &은 참조변수가 아니고 x의 주소를 가져온다. = 연산자의 오른쪽 에 있는 것을 기억하자.

참조변수 &

#include <iostream>

int main(){
    int x = 4;
    int &a = x;

    return 0;
}

c++ 에서 참조변수는 다음과 같이 선언과 초기화를 한다. 이때 &는 = 연산자 왼쪽 에 있다.

주소를 가져올 때 & 는 오른쪽, 참조변수를 사용할 때는 왼쪽