C++ 프로그래머라면, 최근 몇 년 동안 언어에 추가된 "초기화 리스트", "일관된 초기화", 그리고 "멤버 초기화"와 같은 용어를 들어봤을 것입니다. 이러한 기능들은 간단하면서도 강력하며, 더 표현력 있고 효율적인 코드를 작성하고자 한다면 살펴보는 것이 좋습니다.
이러한 새로운 초기화 방법들은 사실 객체를 값의 목록으로 초기화하는 방법입니다. 다시 말해, 생성자에 여러 개의 인수를 전달하거나 배열에 값을 할당하는 경우에 간결하고 읽기 쉬운 방법으로 이를 수행할 수 있습니다.
1. 초기화 리스트
"C++"에서 "초기화"라는 용어는 새로운 것이 아니며, 과거에도 여러 가지 변수 초기화 방법이 제공되어 왔습니다. 그러나 최신 C++에서 도입된 일관된 초기화 구문과 초기화 리스트는 초기화 프로세스를 크게 단순화하고 객체 및 컨테이너 초기화의 가능성을 확대시켰습니다.
과거의 C++에서는 변수를 종류에 따라 생성자 초기화 리스트, 기본값 또는 대입 연산자와 같은 여러 가지 방법으로 초기화할 수 있었습니다.
예를 들어:
int x = 42; // initialization with a default value
std::string str("hello"); // initialization with a constructor
int arr[] = {1, 2, 3}; // initialization with an array initializer
이러한 방법들은 잘 작동했지만, 변수의 종류에 따라 일관성이 없거나 경우에 따라 혼란스러울 수 있었습니다.
일관된 초기화 구문을 사용하면, 변수를 중괄호를 사용하여 일관된 구문으로 초기화할 수 있으며, 타입이나 내장형 또는 사용자 정의 여부에 관계없이 이를 수행할 수 있습니다.
예를 들어:
int x{42};
std::string str{"hello"};
int arr[]{1, 2, 3};
이 구문은 기존 구문보다 더 간결하고 읽기 쉽습니다. 타입에 따라 괄호, 대괄호 또는 대입 연산자를 사용하는 구문보다 더 간결하며, 초기화 리스트를 사용할 수 있도록 합니다. 초기화 리스트는 중괄호로 묶인 값의 목록으로, 객체나 컨테이너를 간결하고 읽기 쉬운 방법으로 초기화할 수 있습니다.
초기화 리스트는 사용자 정의 타입에도 작동하며, 사용자 정의 생성자 또는 멤버 초기화를 사용하여 객체를 초기화할 수 있습니다. 이는 초기화가 복잡하고 오류가 발생할 수 있는 복잡한 데이터 구조에 특히 유용합니다.
2. 일관된 초기화
일관된 초기화 구문은 내장형 또는 사용자 정의 여부와 상관없이 일관된 구문을 사용하여 객체를 초기화할 수 있도록 합니다. 이 구문은 초기화 값을 중괄호로 묶어서 다음과 같이 사용됩니다:
int x {42};
std::vector<int> v {1, 2, 3};
이는 객체 초기화를 위해 타입에 따라 괄호, 대괄호 또는 대입 연산자를 사용하는 기존 구문보다 더 간결하고 읽기 쉬운 방법입니다.
또한, 일관된 초기화 구문은 초기화 리스트를 사용할 수 있도록 합니다. 초기화 리스트는 중괄호로 묶인 값의 목록으로, 객체나 컨테이너를 간결하고 읽기 쉬운 방법으로 초기화할 수 있습니다. 예를 들어:
std::vector<int> v {1, 2, 3};
std::map<std::string, int> m {
{"one", 1},
{"two", 2},
{"three", 3}
};
이 예제에서 초기화 리스트는 정수 벡터와 문자열-정수 쌍 맵을 여러 값으로 초기화하는 데 사용됩니다. 이 구문은 복수의 함수 호출 또는 복잡한 생성자를 필요로 하는 기존 구문보다 더 간결하고 읽기 쉽습니다.
초기화 리스트는 사용자 정의 타입에도 사용할 수 있으며, 사용자 정의 생성자 또는 멤버 초기화를 사용하여 객체를 초기화할 수 있습니다. 예를 들어:
class Point {
public:
Point(int x, int y) : m_x(x), m_y(y) {}
private:
int m_x, m_y;
};
Point p {10, 20};
이 예제에서는 두 개의 정수를 포함하는 초기화 리스트를 사용하여 Point 클래스의 객체를 초기화하며, 이 값은 Point 생성자에 전달되어 멤버 변수를 초기화합니다.
초기화 리스트는 클래스 멤버 변수를 생성자 초기화 리스트 또는 클래스 정의 내에서 직접 초기화하는 데 사용할 수 있습니다. 이를 통해 보다 간결하고 읽기 쉬운 코드를 작성할 수 있으며, 멤버 변수의 초기화에 대한 효율성도 높일 수 있습니다.
3. 멤버 변수 초기화
일관된 초기화 구문과 초기화 리스트의 추가적인 이점 중 하나는 클래스 멤버 변수를 클래스 정의 내에서 직접 초기화할 수 있다는 것입니다. 이 기능을 멤버 변수 초기화라고 하며, 멤버 변수를 선언 시 기본값 또는 사용자 지정값으로 초기화할 수 있습니다. 이는 생성자 코드를 추가로 작성하지 않고도 멤버 변수가 항상 올바르게 초기화되도록 보장하는 좋은 방법입니다.
현대의 C++에서는 중괄호를 사용하여 클래스 멤버 변수를 직접 초기화할 수 있습니다. 이를 "중괄호를 사용한 멤버 초기화"라고 하며, 멤버 변수를 초기화하는 더 간결하고 읽기 쉬운 방법을 제공합니다.
이 기능을 사용하려면 멤버 변수 선언 이후에 중괄호 안에 초기화 값을 묶으면 됩니다. 예를 들어:
class MyClass {
public:
MyClass() {}
private:
int m_x { 0 };
std::string m_str { "default" };
};
이 예제에서는 멤버 변수 m_x가 0으로 초기화되고, m_str이 "default" 문자열로 초기화됩니다. 이 초기화는 생성자 초기화 리스트 없이 MyClass의 새 인스턴스가 생성될 때 자동으로 수행됩니다.
중괄호를 사용한 멤버 초기화는 배열 및 사용자 정의 타입을 포함한 모든 유형의 멤버 변수에 대해 작동합니다. 예를 들어:
class MyClass {
public:
MyClass() {}
private:
int m_array[3] { 1, 2, 3 };
std::vector<int> m_vec { 1, 2, 3 };
};
이 예제에서는 멤버 변수 m_array가 세 개의 정수 배열로 초기화되고, m_vec가 세 개의 정수를 가진 벡터로 초기화됩니다. 이 초기화는 생성자 초기화 리스트 없이 MyClass의 새 인스턴스가 생성될 때 자동으로 수행됩니다.
중괄호를 사용하여 멤버 초기화를 수행하면 여러 가지 이점이 있습니다. 첫째로, 클래스 정의 내에서 멤버 변수를 직접 초기화할 수 있으므로 코드를 더 간결하고 읽기 쉽게 만들 수 있습니다. 둘째로, 생성자 코드나 초기화 리스트를 추가로 작성하지 않아도 멤버 변수가 항상 올바르게 초기화되도록 보장합니다.
결론적으로, 중괄호를 사용한 멤버 초기화는 현대의 C++에서 유용한 기능으로, 클래스 멤버 변수의 초기화 프로세스를 크게 단순화할 수 있습니다. C++ 코드에서 이 기능을 사용하면 초기화 코드를 더 간결하고 읽기 쉽게 작성할 수 있으며, 멤버 변수가 항상 올바르게 초기화되도록 보장할 수 있습니다. 이 기능을 적극적으로 활용하면 보다 효율적인 C++ 코드를 작성할 수 있습니다.
4. 벡터에 초기화 리스트를 사용한 insert(), emplace_back() 함수
초기화 리스트를 사용하는 또 다른 유용한 기능은 초기화 리스트 인수를 사용하여 함수의 메서드를 호출하는 경우입니다. 벡터에 여러 요소를 새로 할당하는 assign()이나 요소를 추가하는 insert() 함수가 이런 경우인데. 이 기능을 사용하면 루프나 여러 함수 호출 없이 여러 요소를 한 번에 벡터에 추가할 수 있습니다.
이 기능을 사용하려면 초기화 값을 포함하는 initializer list를 전달하여 벡터의 assign(), insert() 등의 함수를 호출하기만 하면 됩니다. 예를 들어:
std::vector<int> v{1, 2, 3};
v.assign({ 4, 5, 6 });
v.insert(v.end(), { 7, 8, 9, 10 });
이 예에서 v 벡터는 값 1, 2, 3으로 초기화된 후, assign() 함수로 값 4, 5, 6을 다시 할당하고, insert() 함수로 벡터에 값을 추가할 수 있습니다.
초기화 리스트 인수를 사용하는 insert() 함수는 루프나 여러 함수 호출 대신 여러 요소를 한 번에 벡터에 추가할 수 있는 더 간결하고 효율적인 방법입니다. 또한 사용자 정의 형식과 함께 사용할 수 있습니다. 단, 해당 형식이 initializer list 인수를 수용하는 생성자가 있어야 합니다.
이 외에도 emplace_back() 함수를 사용하여 벡터에 새 요소를 추가할 수 있습니다. 이 함수는 새 요소들을 벡터의 끝에 그 자리에서 생성하기 때문에 불필요한 복사나 재할당을 방지합니다. 예를 들어:
std::vector<std::string> v;
v.emplace_back("hello", "world");
이 예에서 v 벡터는 처음에 비어 있으며, 그 후 emplace_back() 함수가 두 개의 문자열을 포함하는 초기화 리스트와 함께 호출됩니다. 이렇게 하면 값이 "hello"와 "world"인 새 문자열 객체가 벡터의 끝에 In-Place로 생성됩니다.
초기화 리스트를 사용하는 insert() 및 emplace_back() 함수는 더 나은 효율성과 가독성을 제공하여 여러 요소를 한 번에 벡터에 추가할 수 있는 유용한 기능입니다. C++ 코드에서 이러한 함수를 사용하여 벡터 작업을 간소화하고 성능을 향상시킬 수 있습니다.
결론
Initializer list, uniform initialization, member initializer 등 C++에서 제공하는 이러한 초기화 방법들은 변수 초기화 방법을 단순화하고 일관성 있게 만들어 줍니다. 예전에는 변수의 타입에 따라 괄호, 대괄호, 할당 연산자 등을 사용해야 했지만, 이제는 중괄호만 사용하여 초기화가 가능합니다. 이렇게하면 여러 가지 초기화 방법을 하나의 통일된 문법으로 처리할 수 있으며, 복잡한 데이터 구조에서 초기화를 더욱 간편하게 처리할 수 있습니다.
또한 initializer list는 사용자 정의 타입과 함께 사용할 수 있어 커스텀 생성자나 멤버 변수 초기화기를 사용하여 객체를 초기화할 수 있습니다. 멤버 변수 초기화를 사용하면 클래스 정의 내에서 멤버 변수를 초기화할 수 있으므로 코드를 더 간결하고 읽기 쉽게 만들 수 있습니다.
추가로, 모던 C++에서 제공하는 initializer list를 사용하면, vector를 한 번에 여러 개의 요소를 추가할 수 있는 insert() 함수를 사용할 수 있습니다. 이 함수를 사용하면 루프나 여러 개의 함수 호출 없이 vector에 여러 요소를 추가할 수 있습니다. 또한, emplace_back() 함수를 사용하여 vector에 새로운 요소를 추가할 수도 있습니다. 이 함수는 새로운 요소를 vector의 끝에 생성하기 때문에 불필요한 복사나 할당을 방지하며 효율성을 높일 수 있습니다.
이러한 새로운 초기화 방법들은 C++ 프로그래밍을 더욱 쉽고 간결하게 만들어 줍니다. 초기화 코드를 간편하고 읽기 쉽게 작성하여 효율성을 높이고, 초기화를 제대로 수행하도록 보장하며, vector, map 등 컨터이너 객체의 처리 연산을 단순화하여 프로그래밍 생산성을 높이는 데 도움이 됩니다.
'C++' 카테고리의 다른 글
Squared Length를 이용한 3D 좌표의 빠른 거리 비교 방법 (0) | 2023.04.22 |
---|---|
버전관리(GIT, SVN)에 친화적인 C++ 코딩 스타일 (0) | 2023.04.22 |
SinCos() 함수를 사용한 빠른 sin, cos 계산 (2) | 2023.03.12 |