참조자 (Reference)

C언어 에서 어떤 변수를 가르키고 싶을때 포인터로 주소값을 가져와 사용함. C++에서는 참조자 (Reference)를 사용하여 포인터처럼 사용할 수 있음

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

int change_val_pointer(int *p) {
  *p = 3;
  return 0;
}
int change_val_reference(int &p) {
  p = 5;
  return 0;
}

int main(){
  int num = 5;
  change_val_pointer(&num);
  change_val_reference(p);
}


1
2
3
4
int a = 5;
int& a_ref = a;

int& b; // 이런식으로 선언하면 컴파일러 오류
  • 레퍼런스는 반드시 처음 선언될 때 누구를 참조할 것인지 지정해야 됨


1
2
3
4
5
int a = 5;
int& ref = a;

int b =3;
ref = b; // 불가능
  • 레퍼런스는 한번 선언되면 참조를 변경할 수 없음
  • 레퍼런스는 포인터와 다르게 메모리 상에 존재하지 않을 경우가 많다.
    • 윈도우에서 바로가기라고 생각하면 편함


1
2
3
int a = 5;
int& ref1 = a;
int& ref2 = ref1; // ref1, ref2 모두 a를 가르킴
  • 참조의 참조는 불가능 하지만 참조를 복사하는건 가능
    • 윈도우에서 바로가기(1) , 바로가기(2) 처럼 모두 하나를 가르키는것처럼 여러개의 바로가기가 생성되는것과 같음


1
2
3
4
int &ref = 4 //상수는 literal이기때문에 컴파일 오류

const int &ref = 4 // 상수 참조자로 선언하면 가능함
int a = ref; // a = 4 문장과 동일함


레퍼런스의 배열

1
2
3
  int a = 1;
  int b = 2;
  int & arr[2] = {a, b}; 
  • 문법상 배열의 이름은 첫 번째 원소의 주소값으로 변환되기 떄문에 주소값이 존재한다는 의미는 메모리 상에 존재하게 되기 떄문에 문법 오류가 된다.

배열의 레퍼런스

1
2
  int arr[3] = {1,2,3};
  int(&ref)[3] = arr;
  • [ ]의 연산 우선순위가 &보다 높기 때문에 괄호가 없으면 int &(ref[3])과 같이 선언된다.

함수와의 관계

1
2
3
4
5
6
7
int func(){
  int a = 2;
  return a;
}
int main(){
  int b = func();
}
  • 함수 내부의 지역 변수 a의 값은 b에 복사됨(새로운 메모리 공간에 할당). 이때 리턴되는 객체의 크기가 크면 복사되는데 시간이 오래 걸리므로 객체의 레퍼런스를 리턴하는 것이 효율적이다.


1
2
3
4
5
6
7
int& func(){
  int a = 2;
  return a;
}
int main(){
  int b = func();
}
  • 지역 변수의 레퍼런스가 리턴되는 경우 레퍼런스는 남고 원본인 a는 함수 리턴과 동시에 삭제되므로 Dangling Reference가 된다.
1
2
3
4
5
6
7
8
9
10
int& func(int& a){
  a = 5;
  return a;
}

int main(){
  int b = 2;
  int c = func(b); // 새로운 메모리에 5가 할당됨
  int& d = func(b); // b의 주소값이 복사됨
}
  • 외부 변수를 받아 리턴되는 경우 주소값의 복사로 전달이 끝남

new, delete

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
int func(int arr_size){
  int *list = new int[arr_size];
  for(int i = 0; i < arr_size; i++{
    list[i] = i;
  }
  
  delete[] list;
}

typedef struct Animal{
  char name[30];
  int age;
} Animal;

int func2(int size) {
  Animal *animal_list;
  for(int i = 0; i < size; i++){
    animal_list[i] = new Animal;
  }
  
  // delete
  for(int i=0; i < size; i++){
    delete animal_list[i];
  }
}

객체 (Object)

추상화(abstraction), 인스턴스 변수(instance variable), 인스턴스 메소드(instance method), 캡슐화(Encapsulation), class, member variable, member function

class는 객체의 설계도, 객체는 instance class

Object 챕터 문제 해결
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Date {
  int year_;
  int month_;
  int day_;
  int m_day[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  
  public:
    void SetDate(int year, int month, int date){
      year_ = year;
      month_ = month;
      day_ = date;
      
      if (year_ % 4 == 0) {
        m_day[1] = 29;
      }
      else {
        m_day[1] = 28;
      }
    }
    void AddDay(int inc) {
      day_ = day_ + inc;
      while (day_ > m_day[month_ - 1]) {
        day_ = day_ - m_day[month_ - 1];
        AddMonth(1);
      }
    }
    void AddMonth(int inc) {
      month_ = month_ + inc;
      while (month_ > 12) {
        month_ = month_ - 12;
        AddYear(1);
      }
    }
    void AddYear(int inc) {
      year_ = year_ + inc;
      if (year_ % 4 == 0) {
        m_day[1] = 29;
      }
      else {
        m_day[1] = 28;
      }
    }
    
    void ShowDate(){
      printf("%d년 %d월 %d일\n", year_, month_, day_);
    }
};

함수의 오버로딩, 생성자

  • C++에서 같은 이름의 함수를 호출했을때 사용하는 인자(Parameter)를 보고 구별한다.

C++ 컴파일러에서 함수를 오버로딩하는 과정

1단계

자신과 타입이 정확히 일치하는 함수를 찾는다.

2단계

1단계에서 정확히 일치하는 타입이 없을떄는 아래의 형변환 규칙을 통해 일치하는 함수를 찾는다.

  • Char, unsigned char, short, short => int
  • unsigned short => int or unsigned int
  • Float => double
  • Enum => int

3단계

좀더 포괄적인 형변환을 통해 일치하는 함수를 찾는다.

  • 임의의 숫자(numeric), Enum 타입은 다른 숫자타입으로 변환(예를들어 float -> int)
  • Null은 포인터 타입이나 숫자타입인 0으로 변환된다.
  • 포인터는 void 포인터로 변환된다.

4단계

유저 정의된 타입 변환으로 일치하는 것을 찾는다.

1
2
3
4
5
6
7
8
void print(int x) {...}
void print(char x) {...}

int main(){
  double a = 3.2f;
  
  print(a);
}
  • 이 경우 3단계에서 doublecharint 2개로 변환 될 수 있는데, 같은 단계에서 일치하는 함수가 2개이상이면 모호하기 떄문에 컴파일러에서 오류가 발생한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Date {
  int year_;
  int month_;
  int day_;
  
  Date() { // default construct
    year_ = 2012;
    month_ = 7;
    day_ = 12;
  }
  Date(int year, int month, int day){ // construct
    year_= year;
    month_ = month;
    day_ = day;
  }
  ...
}

Reference

https://modoocode.com/

Tags:

Categories:

Updated:

Leave a comment