갓똥
나는야 프로그래머
갓똥
전체 방문자
오늘
어제
  • 분류 전체보기 (186)
    • 프로그래밍 (146)
      • 자바 (9)
      • 안드로이드 (2)
      • 유니티 (20)
      • C++ (38)
      • C# (56)
      • HTML (2)
      • 파이썬 (3)
      • 자료구조 (2)
      • 알고리즘 (0)
      • 문제풀이 (4)
      • 디자인 패턴 (7)
      • 카카오톡 봇 (1)
      • 엑셀 (1)
      • 기타 (1)
    • 게임 (21)
      • 테일즈위버 (0)
      • 카이로소프트 (1)
      • 순위 (19)
      • 기타 (1)
    • 일상 (13)
      • 카페 (1)
      • 방탈출 (12)
    • 기타 (6)
      • 웃긴자료 (5)

블로그 메뉴

  • 홈
  • 방명록

공지사항

인기 글

태그

  • pc게임 순위
  • 전세계 게임 매출
  • c# coroutine
  • 게임 디자인 패턴
  • c# 코루틴
  • 게임 매출 순위
  • 글로벌게임매출
  • 자바
  • 2020년 게임 매출
  • c# delegate
  • 게임매출순위
  • 전세계게임매출순위
  • 강남 방탈출
  • C++
  • c# unboxing
  • pc 게임 순위
  • Unity Graph
  • 유니티 골드그래프
  • C++ 상속
  • 모바일 게임 순위
  • C++ 소멸자
  • C# 예외 처리
  • C++ virtual
  • 유니티 그래프
  • 알고리즘
  • c# Thread
  • 유니티 그래프 그리기
  • c# collection
  • C# boxing
  • 롤 골드그래프

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
갓똥

나는야 프로그래머

[C++] 레퍼런스(reference)
프로그래밍/C++

[C++] 레퍼런스(reference)

2019. 10. 22. 00:40
728x90
반응형

1. reference

#include <iostream>

int main() {
    int n = 10;
    n = 20;
    
    int& r = n; // 레퍼런스
    
    r = 30; // n = 30. n에 30을 넣은것과 같음
    
    std::cout << n << std::endl;
    std::cout << r << std::endl;  // 같음
    
    std::cout << &n << std::endl;
    std::cout << &r << std::endl; // 같음
}

    - 변수

        => 메모리의 특정 위치를 가르키는 이름

        => 코드안에서 해당 메모리에 접근하기 위해 사용

 

    - 레퍼런스 변수

        => 기존 변수(메모리)에 또 다른 이름(alias)를 부여하는 것

 

1.1 함수 인자 전달 방식

#include <iostream>

void f1(int n) { ++n; }
void f2(int* p) { ++(*p); }
void f3(int& r) { ++r; }

int main() {
    int a = 0, b = 0, c = 0;
    
    f1(a);
    f2(&b);
    f3(c);
    
    std::cout << a << std::endl;
    std::cout << b << std::endl;
    std::cout << c << std::endl;
    
    int* p = &n;
    int& r = n;
}

    - int a = 0, b = 0, c = 0; 에서 초기화 했을 때의 메모리

 

    - f1(a)의 실행 과정

        => f1함수에서 int n을 새로운 메모리에 할당(n)

        => 새로운 메모리에 선언된 변수의 값이 증가

        => C에서의 call by value / 원본을 수정할 수 없다.

        => 실행결과는 0

 

    - f2(&b)의 실행 과정

        => 포인터 변수가 만들어지며, 2000이라는 주소를 받게 됨

        => 또 다른 메모리를 잡긴 했지만 주소를 갖고 있고, 2000번지를 따라가서 값이 증가되어 b가 1증가됨

        => C에서의 call by reference / 원본을 수정할 수 있다.

        => 실행결과는 1

 

    - f3(c)의 실행 과정

        => C++의 reference / 원본을 수정할 수 있다.

 

1.2 포인터(Pointer)와 레퍼런스(Reference)

#include <iostrea>

int main() {
    int n = 10;
    
    int* p1 = &n;
    int& r1 = n;
    
    int* p1;
    int& r2 = 0;
    
    *p1 = 20;
    r1 = 20; 
    
    if(p1 != 0) {}
    //if(r1 != 0) {}
}

 - 유사한 점

    => 기존 변수(메모리)를 가리킨다.

 

 - 차이점

 


2. const reference

#include <iostream>

struct Date {
    int year;
    int month;
    int day;
};

void move(Date d) { // call by value
    d.year = 1000;  // 값이 변하지 않는다.
}

int main() {
    Date date = {2019, 10, 22};
    
    move(date);
    
    std::cout << date.year << std::endl;
}

  2.1 call by value의 특징

    => 인자로 전달된 객체의 복사본이 생성된다.

    => 원본 객체를 변경할 수 없다. - 안전하다.

    => 하지만, 복사본에 대한 오버헤드가 있다.

 

  2.2 인자의 값을 변경하지 못하는 함수를 만들려면

// void move(Date d)
void move(Date& d) {
    d.year = 1000;
}

    => 레퍼런스로 바꿔준다.

    => 하지만 레퍼런스로 받음으로써 원본의 값이 변경될 수 있다.

void move(const Date& d) {
    // d.year = 1000;  - error
}

    => 이 때, const를 붙여주면 원본의 값을 바꿀 수 없게 된다.

    => 여기서는 값을 변경하기 위해 레퍼런스를 쓰는게 아닌, 값을 못 바꾸게 하기 위해 레퍼런스를 사용했다.

 

  2.3 const reference의 장점

    => 인자에 대한 복사본을 만들지 않는다.

    => 복사 생성자와 소멸자가 호출되지 않는다.

 

  2.4 함수 인자 전달 방법 정리

#include <iostrea>

void move(? x) {

}

int main() {
    int n = 10;
    
    // move 함수에서는 절대로 n의 값을 변경하면 안된다.
    move(n);
    
    std::cout << n << std::endl; // 반드시 10이 나와야 한다.
}

    - 조건 : n의 값을 절대 변경하면 안된다. 위의 move함수의 인자타입은 어떻게 들어가야 할까?

    - move(int x) - call by reference | move(const int& x) - const reference

    - 위에선 복사본이 만들어지기 때문에 const reference가 좋다고 했지만, int타입은 메모리의 용량이 크지도 않고, 이러한 표준 타입은 call by value가 참조로 받았을 때보다 최적화가 훨씬 잘 되어 있다.

    - 또한 참조로 받았을 때, 상황에 따라 메모리가 정말 안잡히는게 아닌 내부적인 원리로 어떤 포인터가 잡힐 수 있다.

    - 따라서 이러한 int or double타입(표준 타입)일 경우 call by value가 더 낫다.

 

    1. 함수 안에서 인자의 값을 변경하고 싶다면

        => 포인터 또는 참조를 사용해서 전달 받는다.

    2. 함수 안에서 인자의 값을 변경하지 못하게 하려면

        - primitive type => call by value가 좋다.

        - user define type => const reference가 좋다.

 


3. reference return

struce Point {
    int x;
    int y;
};

void t1(Point  pt) {} // 복사본 생성
void t2(Point& pt) {} // 복사본 생성 안함

  3.1 함수 인자

    - call by value      => 복사본을 생성한다.

    - call by reference => 복사본을 생성하지 않는다.

 

struce Point {
    int x;
    int y;
};

Point pt = {0, 0};

Point pm() {  // 값 타입 반환 return by value
    retrun pt;
}

int main() {
    pm().x = 10; // error
}

  3.2 함수 반환값

    - main함수내의 pm()함수는 pt를 반환한다. 그럼 pm()자리에 pt가 오게 되는데 이 pt가 원본일까?

    - 값타입을 반환했기 때문에 리턴 용 임시 객체가 생성되어 반환된다.

    - 특히 리턴 용 임시 객체는 C++에서 등호의 왼쪽에 올 수 없게 되어 main함수 내의 문법은 에러가 난다.

struce Point {
    int x;
    int y;
};

Point pt = {0, 0};

// Point pm() { // 값 타입 반환 return by value
Point& pm() {  
    retrun pt;
}

int main() {
    pm().x = 10; // ok
}

 

  3.3 reference 와 함수 반환값

#include <iostream>

int x = 10;

int  t1() { return x; } // 값
int& t2() { return x; } // 참조

int main() {
    t1() = 20; // 10 = 20 - error
    t2() = 20; // x = 20  - ok
}

    * 주의! => 절대, 지역변수를 참조로 반환하면 안된다.

 


4. rvalue reference

int main() {
    int v1 = 0, v2 = 0;
    
    v1 = 10; // ok
    10 = v1; // error
    v2 = v1; 
    
    // lvalue reference
    int& r1 = v1; // ok
    int& r2 = 10; // error
    
    // const lvalue reference
    const int& r3 = v1; // ok
    const int& r4 = 10; // ok
    
    // rvalue reference : rvalue만 가르킨다.
    int&& r5 = v1; // error
    int&& r6 = 10; // ok
}

  4.1 lvalue와 rvalue

 

  4.2 reference 규칙

 

  4.3 rvalue reference가 사용되는 분야

    => move semantics

    => perfect forwarding

728x90
반응형

'프로그래밍 > C++' 카테고리의 다른 글

[C++] 동적 메모리 할당, nullptr  (0) 2019.10.27
[C++] Explicit Casting  (0) 2019.10.25
[C++] range for / if init / if constexpr  (0) 2019.10.18
[C++] C언어와 다른 C++ 함수(2)  (0) 2019.10.11
[C++] C언어와 다른 C++ 함수(1)  (0) 2019.10.09
    '프로그래밍/C++' 카테고리의 다른 글
    • [C++] 동적 메모리 할당, nullptr
    • [C++] Explicit Casting
    • [C++] range for / if init / if constexpr
    • [C++] C언어와 다른 C++ 함수(2)
    갓똥
    갓똥
    공부하며 알아가는 내용을 정리해 봅니다.

    티스토리툴바