C++ Chapter 9.13 : initializer_list

Date:     Updated:

카테고리:

태그:

인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 C++ 강의를 듣고 정리한 필기입니다. 😀
🌜 [홍정모의 따라 하며 배우는 C++]강의 들으러 가기!


chapter 9. 연산자 오버로딩 : initializer_list

🔔 소개

  • 컨테이너의 초기화를 편리하게 할 수 있도록 도와주는 템플릿이다.

#include <initializer_list>

auto li = { 10, 20, 30 };

li의 타입은 std::initializer_list<int> 이다. 이처럼 {} 중괄호를 사용하여 이니셜라이저 리스트를 생성할때 타입이 auto이면 std::initializer_list 타입의 객체가 된다.


🔔 initializer_list 를 인수로 받는 생성자

std::initializer_list 객체를 인수로 받는 생성자를 구현해 놓으면, 대입 연산자 =와 함께 {} 중괄호를 사용해서 생성자를 호출할 수 있다. 이때의 중괄호가 바로 std::initializer_list 객체가 되기 때문.

#include <iostream>
#include <cassert>
#include <initializer_list>

using namespace std;

class IntArray
{
private:
	unsigned m_length = 0;
	int *m_data = nullptr;

public:
	IntArray(unsigned length) 
		: m_length(length)
	{
		m_data = new int[length];
	}

	IntArray(const std::initializer_list<int> &list)
		:IntArray(list.size()) // 위임 생성자
	{
		int count = 0;
		for (auto & element : list)
		{
			m_data[count] = element;
			++count;
		}
	}

	~IntArray()
	{
		delete[] this->m_data;
	}

	friend ostream & operator << (ostream & out, IntArray & arr)
	{
		for (unsigned i = 0; i < arr.m_length; ++i)
			out << arr.m_data[i] >> " ";
		out << endl;
		return out;
	}
};

int main()
{
	IntArray int_array = { 1,2,3,4,5 };  // ⭐ 중괄호로 생성자 호출이 가능해짐!

	cout << int_array << endl;

	return 0;
}
  • IntArray(const std::initializer_list<int> &list)
    • std::initializer_list 타입의 참조 객체를 인수로 받는 생성자
      • ⭐ int 원소들이 들은 {}중괄호를 인수로 넘기면 그게 바로 std::initializer_list 타입의 객체 list가 된다!
    • 생성자 초기화 리스트에서 위임 생성자IntArray(list.size())를 호출한다.
      • initializer_list 템플릿은 여러 함수를 지원한다. 그 중 하나인 size(){}, 즉 std::initializer_list 타입의 객체 안에 든 원소의 개수를 리턴한다.
      • {}크기의 동적 배열을 할당 받아 그 주소를 m_data 에 대입한다.
    • for문 돌려 {}, 즉 std::initializer_list 타입의 객체 안에 든 원소들을 m_data 가 가리키는 동적 배열 원소로 복사해준다.
      • 이때, m_data[count] = list[count] 는 안된다!
        • initializer_list 템플릿은 대괄호를 지원하지 않아 list[count]라고 쓸 수 없다.
          • [] 첨자 연산자 오버로딩이 안되어 있는 것 같다!
  • IntArray int_array = { 1,2,3,4,5 };
    • std::initializer_list 타입의 참조 객체를 인수로 받는 생성자가 호출된다.
    • 문제 없이 IntArray 타입의 객체 int_array의 멤버 m_data가 가리키는 동적 배열 원소로 1, 2, 3, 4, 5가 초기화 된다.
    • = 대입 연산자는 빼도 상관없다.


🔔 주의 사항

  1. initializer_list 템플릿은 대괄호를 지원하지 않는다.
    • 따라서 std::initializer_list 객체에 첨자 []를 쓸 수 없다.
    • [] 첨자 연산자 오버로딩이 안되어 있는 것 같다!
  2. initializer_list 템플릿은 얕은 복사를 한다.
    • 따라서 동적 메모리를 사용하는 포인터를 사용하는데 {}std::initializer_list 객체끼리 복사해야 하는 경우가 있다면 깊은 복사를 위해 따로 대입 연산자 오버로딩을 구현해주자.
  3. std::initializer_list 타입의 참조 객체를 인수로 받는 생성자는 생성자 초기화에 사용되는 {}보다 우선된다.
    • ()말고 {}로 생성자를 호출하는게 자동 형변환을 막아주는 더 엄격한 호출이라고 이 포스트에서 배웠었다.
    • std::initializer_list 타입의 참조 객체를 인수로 받는 생성자가 구현되어 있다면 {}로 생성자 호출시 이 생성자가 더 우선한다는 것에 주의하자.


🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기


댓글남기기