LastMod:

👨‍💻 개인 공부 기록용 블로그 입니다.
💡 틀린 내용이나 오타는 댓글, 메일로 제보해주시면 감사하겠습니다!! (__)

42 Cursus - Cpp Module을 진행하기 위해 정리했었던 C++98 기본 개념들로, C++11, C++14와 다른 내용이 있을 수 있습니다.
각 개념은 정리한 시간 순으로 배치되어 있으며, 한 포스트에 배치된 개념이 크게 관련이 없을 수 있습니다.

참조자 (Reference)

  • 참조자 (Reference)는 포인터와 유사하면서도 다른, 타 변수나 상수를 가리키는 방법이다.
  • 기존 변수에 대한 또 다른 이름을 제공한다고 보면 된다. (alias)
#include <iostream>

//레퍼런스는 함수의 인자로도 쓰일 수 있다.
int change_val(int &p) {
	p = 3;
	return 0;
}

int main() {
  int a = 3;
  int& another_a = a;

	//컴파일 타임에 another_a 가 a로 대치됨
  another_a = 5; 
	// 따라서 a가 5로 변경된다.

	//아래 코드는 a를 다시 3으로 변경시킨다.
	change_val(a); 
	//change_val 함수가 인자로 레퍼런스를 받기 때문에, 
	//a의 값을 복사해서 넘기는게 아니라 a를 그대로 가져가게 된다.
	//정확히는 a를 넘길 때에, 함수 내에서 int& p = a 로 p가 정의된 후 넘어간다고 생각하면 된다.
  return 0;
}
  • 레퍼런스는 선언 시에 반드시 누구의 별명이 될 것인지 지정해야 하며, 한 번 지정하면 절대로 변경할 수 없다.
  • 또한 레퍼런스는 포인터와 다르게, 메모리 상에 존재하지 않을 수 있다.
    • 단순 alias의 기능을 하는 경우에는, 조금만 생각해보면 메모리 상에 존재할 이유가 없다. 컴파일 타임에 대치해주면 되기 때문이다.
    • 위와 같이 함수의 인자로 레퍼런스를 받을 때에는, 그 인자 레퍼런스는 스택 메모리를 차지한다.
  • 레퍼런스의 레퍼런스, 레퍼런스의 배열, 레퍼런스의 포인터는 존재할 수 없다.
  • 레퍼런스를 리턴하는 함수는 존재할 수 있지만, 지역변수의 레퍼런스를 리턴하지 않도록 주의해야 한다.
    • 금지된 동작은 아니지만, seg fault를 유발시키기 딱 좋다.

Const 키워드 와 초기화 리스트 (Initialization Lists)

일반적인 상수의 의미

const int a = 1;

a = 2; //compile error
  • 말 그대로, 초기 선언 후 값을 변경할 수 없는 변수를 이야기 한다.
  • 하지만 const 상수를 사용하는 것 보다, #define을 이용한 매크로 상수나 enum을 활용한 열거형 상수의 사용이 권장된다.

const 포인터 변수

int a = 1;
int b = 2;
const int *ptr1 = &a; //*ptr1 자체를 상수화 (int 의 상수화)
int * const ptr2 = &a; //ptr2를 상수화 (int * 의 상수화)

*ptr1 = 3; //compile error
a = 2; //OK
ptr2 = &b; //complie error

//합치면 아래와 같이 쓸 수 있다. (ptr3이 가리키는 대상과 그 값을 모두 상수화)
const int * const ptr3 = &b;
  • 위와 같이 const의 위치에 따라, 상수화 시키는 대상이 다르다.

const 멤버 함수

  • 일반적으로 함수에는 const 키워드를 붙일 수 없다.
  • 그러나 클래스의 멤버 함수는 const 키워드를 가질 수 있다.
    • int fn(void) const;
  • const 멤버 함수는 해당 함수 내에서는 멤버 변수를 상수화 시키는 의미로 사용된다.
    • 즉, 자신이 호출하는 객체를 수정하지 않는 읽기 전용 함수라는 이야기이다.
  • 따라서, 해당 멤버 함수 내의 지역변수는 정상적인 사용이 가능하지만, 멤버 변수는 변경시킬 수 없다.

초기화 리스트 (Initialization Lists) 와 const 멤버 변수

  • 클래스의 멤버 변수를 초기화 하는 방식

      //일반적인 변수는
      int a = 10;
      int b;
      b = 10;
      //이렇게, 선언 직후 초기화 와 선언 후 대입이 큰 차이가 없지만
      //클래스에서는 아주 큰 차이를 불러온다.
        
      //Person 이라는 클래스가 있고 멤버로 나이를 가진다고 가정했을 때,
      Person p1 = Person(42); //'멤버를 초기화 하는 생성자' 호출
      Person p2; //디폴트 생성자 호출
      p2 = Person(42); //'멤버를 초기화 하는 생성자' 호출 -> 대입 연산자 호출
      //무려 연산이 3단계로 늘어나는 효과를 가져온다!
    
  • 생성자를 정의할 때, 콜론(:) 후 멤버들을 나열하여 소괄호로 초기화 할 수 있다.
    • Person() : _age(42), _name(”HJ”) { //생성자 정의 };
  • 초기화 리스트를 반드시 사용해야 하는 경우도 존재한다.
    1. 멤버 변수로 레퍼런스 타입을 가질 때
    2. 멤버 변수로 const 타입을 가질 때
  • 레버런스와 const 변수는 대입이 불가능 하기 때문에, 반드시 초기화 리스트를 사용하여야 한다.

Reference

CPP 레퍼런스 (Reference)

모두의 코드 - Reference

[C++ 강좌] const 위치의 의미와 사용 방법

Leave a comment