선언시 새로운 C ++ 11 멤버 초기화 기능이 초기화 목록을 쓸모 없게 만들었습니까?
C ++ 11을 사용하면 이제 헤더 선언에서 클래스 멤버를 초기화 할 수 있습니다.
class aClass
{
private:
int mInt{100};
public:
aClass();
~aClass();
};
그래서 조금 혼란 스럽습니다. 전통적으로 생성자의 초기화 목록은 멤버 초기화에 사용되었습니다.
aClass::aClass()
: mInt(100)
{
...
}
선언시 새로운 C ++ 11 멤버 초기화 기능이 초기화 목록을 쓸모 없게 만들었습니까? 그렇지 않다면 다른 것보다 하나의 장점은 무엇입니까? 선언시 초기화가 유리하거나 초기화 목록이 유리한 상황은 무엇입니까? 하나는 언제 다른 것보다 사용해야합니까?
아니요,이 기사 는 클래스 멤버 초기화 섹션 에서 새로운 C ++ 11 초기화 양식에 대해 알아보기 ( 강조 :
동일한 데이터 멤버에 클래스 멤버 이니셜 라이저와 생성자에 mem-init가 모두있는 경우 후자가 우선합니다. 실제로 생성자에 해당 멤버에 대한 명시 적 mem-init가없는 경우 사용되는 클래스 멤버 이니셜 라이저 형식으로 멤버 에 대한 기본값을 지정하여이 동작을 활용할 수 있습니다 . 그렇지 않으면 생성자의 mem-init가 적용되어 클래스 멤버 이니셜 라이저를 재정의합니다. 이 기술은 여러 생성자가있는 클래스에서 유용합니다.
따라서 클래스 멤버 초기화가 편리하더라도 초기화 목록의 필요성을 제거하지는 않지만 대신 두 기능이 함께 작동하여 기본값을 지정하고 필요할 때 재정의하는 좋은 방법을 제공합니다. 이것은 또한 Bjarne Stroustrup 이 그것을 보는 방법 인 것 같습니다 .
이렇게하면 타이핑이 약간 절약되지만 실제 이점은 여러 생성자가있는 클래스에서 제공됩니다. 종종 모든 생성자는 멤버에 대해 공통 이니셜 라이저를 사용합니다.
공통 이니셜 라이저가있는 멤버의 예를 제공합니다.
class A {
public:
A(): a(7), b(5), hash_algorithm("MD5"), s("Constructor run") {}
A(int a_val) : a(a_val), b(5), hash_algorithm("MD5"), s("Constructor run") {}
A(D d) : a(7), b(g(d)), hash_algorithm("MD5"), s("Constructor run") {}
int a, b;
private:
HashingFunction hash_algorithm; // Cryptographic hash to be applied to all A instances
std::string s; // String indicating state in object lifecycle
};
그리고 말한다 :
hash_algorithm과 s에 각각 하나의 기본값이 있다는 사실은 복잡한 코드로 인해 손실되며 유지 관리 중에 쉽게 문제가 될 수 있습니다. 대신 데이터 멤버의 초기화를 제거 할 수 있습니다.
class A {
public:
A(): a(7), b(5) {}
A(int a_val) : a(a_val), b(5) {}
A(D d) : a(7), b(g(d)) {}
int a, b;
private:
HashingFunction hash_algorithm{"MD5"}; // Cryptographic hash to be applied to all A instances
std::string s{"Constructor run"}; // String indicating state in object lifecycle
};
참고 : C ++ 11의 단점
There is one disadvantage to using in class member initialization in C++11 since it makes a class a non-aggregate we can no longer use aggregate initialization which may be rather surprising. This is not the case in C++14 where this restriction was removed. See: C++11 aggregate initialization for classes with non-static member initializers for more details.
No, they are not obsolete.
Initialization lists are still the only way to go if you need constructors arguments to initialize your class members.
class A
{
int a=7; //fine, give a default value
public:
A();
};
class B
{
int b;
public:
B(int arg) : b(arg) {}
B(int arg, bool b) : b(arg) { ... }
};
Note that if both are present, the constructor's init will take effect, overriding the class member initialization, which is useful to specify a default value for a class member.
The way I look at it, in-class initialization is an ehancement of mem-initializer-lists. In C++03, members not listed in a mem-initializer-list were always default initialised. This means the default constructor for classes, and no initialization for primitive types.
In-class initialization simply allows you to specify your own defaults. There are two ways to look at it.
One: if most/all constructors of your class want to provide the same initial value for a member, use an in-class initializer for that member. For other members, use mem-initializer-lists. You'll of course have to use those whenever the initial value depends on constructor arguments.
The other one: provide an in-class initializer for all members, exactly how the default constructor of your class would initialise them. Then, mem-initializer-lists in non-default constructors get the semantics of "how it differs from a default-constructed object."
'Nice programing' 카테고리의 다른 글
| Azure App Service 계획 이름 바꾸기 (0) | 2020.11.18 |
|---|---|
| Python에서 가장 효율적인 그래프 데이터 구조는 무엇입니까? (0) | 2020.11.18 |
| 기본 클래스 메서드에 액세스하기 위해 "using"키워드를 사용해야하는 이유는 무엇입니까? (0) | 2020.11.18 |
| Python의 '열거'함수에 해당하는 Java가 있습니까? (0) | 2020.11.18 |
| : before와 :: before의 차이점은 무엇입니까? (0) | 2020.11.18 |