본문 바로가기

생성자 멤버 초기화 리스트 (Constructor member initializer list) 본문

💘 C++/객체지향의 기초

생성자 멤버 초기화 리스트 (Constructor member initializer list)

Hyonii 2022. 8. 30. 22:37

생성자 멤버 초기화 리스트 (Constructor member initializer list)

생성자의 멤버들을 초기화할 때 사용하는 Initializer list에 대해서 설명드리겠다.

Something이라는 클래스를 만들었다.
int, double, char 타입의 세 가지 멤버를 가지고 있다.
초기화하는 방법은 이전 포스팅에서 여러 번 설명드렸다.

public으로 Something의 constructor를 하나 만들고 초기화를 해줬다.
이때 initializer list라는 것은 조금 더 표현이 우아하다.

이렇게 해주면 된다.
물론 이렇게 Initializer list에서 초기화를 한 다음에 아래 { }에서 다시 값을 바꿔 줄 수 있다.

일단 잘 되나 보기위해서 print함수를 하나 만들었다.
실행시켜보면

초기화 해준 대로 잘 나왔다.


Uniform Initialization in C++11

초기화할 때 괄호( ) 대신에

이렇게 { } 로 바꿔줄 수도 있는데 이렇게 되면 형 변환이 안된다.
괄호로 했을 때와의 차이점이다.
자동으로 캐스팅을 안해주고 막아버린다.
{ }이 좀 더 엄격하다고 보면 된다.

실행시켜보면 똑같이 작동한다.


초기화 리스트를 사용한 배열 멤버 초기화

C++ 11 이후에서는 array도 초기화할 수 있다.

세로로 e 출력
가로로 e 출력


클래스인 멤버 변수 초기화

멤버안에 다른 user defined type
즉, 클래스로 된 멤버가 들어갈 수 있다.

class B를 만들고
class Something에 calss B 타입의 m_b를 만들어줬다.
이번에는 디버거로 찍어보자.

지금 마치 29번째 줄 까지 온 것처럼 보이지만 실제로는 아직 위에서 돌고 있다.
여기서 f11을 누르면

또 누르면

class B의 생성자로 왔다.
m_b_in으로 0이 들어온 것을 볼 수 있다.
왜냐면 밑에서 m_i 가 1로 초기화되고 m_i - 1은 0이기 때문이다.
한 번 더 f11을 눌렀을 때

m_b에 아직 대입이 안된 것은 중괄호를 밑으로 안 내려놔서 그렇다.
한 번 더 f11 누르면

0이 들어왔다.

여기도 0이다.
한 번 더 누르면

이런 순서로 나온다.
의도한 대로 작동하는 것을 확인할 수 있다.


멤버 초기화 리스트 줄 맞추기

줄 맞춤을 잘해주기 어려울 수 있다.
이렇게 가로로 쭉 나열하게 되면 오른쪽으로 점점 길어지게 된다.
코드가 가로로 길면 프로그래머가 힘들어진다.
적당한 타이밍에서 줄 바꿈을 하는 게 일반적인데 코딩 스타일에 따라 좀 다르다.

모든 멤버들을 한 줄씩 차지하게 할 수도 있고

적당히 길이 봐서 이 정도에서 내려주는 스타일도 있다.

그리고 어떤 코딩 스타일에서는 콤마를 밑으로 빼기도 한다.

이게 좀 안 좋아 보인다고 생각할 수도 있는데
이 방식의 장점은 코딩하다 보면 멤버가 새로 추가가 되거나 빠지는 경우가 많다.
코드가 변동이 많을 경우 콤마가 앞에 있으면 좀 편하다.
코딩 스타일은 알아서 선택하거나 일하는 곳 코딩스타일 따라가면 된다.


초기화 우선순위

한 가지 더 설명을 드리자면

여기서도 바로 초기화를 할 수 있다.
예를 들면

이렇게 넣어줄 수 있다.

이렇게 되면 두 군데에서 초기화를 해 줄 수 있게 된다.
과연 둘 중에 어느 쪽이 우선이 될까?

이 경우에는 생성자가 우선이다.

아무튼 non_static member들은 여기서 초기화를 해줄 수 있다.
static member에 대해서는 추후 설명하겠다. 경우가 좀 다르다.
그리고 두 군데에서 동시에 초기화를 했을 경우, 생성자가 우선순위가 더 높다라는 것을 기억하면 된다.
만약에 생성자가 없다면

초기화를 아예 안 하는 것보다는 여기서 해주는 게 훨씬 좋다.

위에서 초기화 해준대로 잘 나온다.

마지막으로 한 가지 더 실험해 볼 것이 있다.

여기서 만약에 별도로 초기화를 해준다고 하면 어떻게 될까?

initializer list에서 초기화를 해주고 이후에 다시 대입을 해준 값이 최종 값이 되었다
이때는 initializer list가 무시되는 것이 아니고 먼저 실행이 되고 난 다음에 { } 부분이 실행이 된 것이다.
예를 들어서

이렇게 해주고 출력해보면

초기화가 되고 거기서 곱하고 더한 값들이 나온다.

코딩할 때 생성자를 사용 안 하고 좀 급하게 빠르게 코딩해야 되는 상황이라면

그냥 public으로 놓고 이런 식으로 default값 넣어서 코딩할 수도 있다.
그리고

생성자 파라미터에 default값 넣어주는 방법도 있다.
그 방법은 이전 포스팅에서 설명드렸다.


요약

  • 멤버 초기화 리스트를 사용하면 값을 할당하지 않고 멤버 변수를 초기화할 수 있다.
  • 생성자 본문에서 값을 할당하는 것보다 성능이 더 우수하다.
  • const 또는 reference 변수와 같이 초기값이 필요한 멤버를 초기화할 수 있는 유일한 방법이다.
  • 멤버 초기화 리스트는 기본 자료형 변수와 클래스 자체인 멤버 모두에서 잘 작동한다.
Comments