기본 생성자와 소멸자에서 "= default"는 "{}"과 어떻게 다릅니 까?
나는 원래 이것을 소멸자에 대한 질문으로 만 게시했지만 이제 기본 생성자를 고려하고 있습니다. 원래 질문은 다음과 같습니다.
클래스에 가상의 소멸자를 제공하고 싶지만 컴파일러가 생성하는 것과 동일한 소멸자를 제공하려면
=default
다음을 사용할 수 있습니다 .class Widget { public: virtual ~Widget() = default; };
그러나 빈 정의를 사용하여 타이핑을 줄이면 동일한 효과를 얻을 수있는 것 같습니다.
class Widget { public: virtual ~Widget() {} };
이 두 정의가 다르게 행동하는 방법이 있습니까?
이 질문에 대한 답변을 기반으로 기본 생성자의 상황이 비슷해 보입니다. 소멸자에 대해 " =default
"와 " {}
"의 의미에 거의 차이가 없다는 것을 감안할 때 기본 생성자에 대한 이러한 옵션 사이에 의미에 거의 차이가 없습니까? 즉, 해당 유형의 객체가 생성되고 파괴되는 유형을 생성한다고 가정하면 왜 말하고 싶습니까?
Widget() = default;
대신에
Widget() {}
?
원래 게시물이 일부 SO 규칙을 위반 한 후이 질문을 확장하면 죄송합니다. 기본 생성자에 대해 거의 동일한 질문을 게시하면 바람직하지 않은 옵션으로 생각났습니다.
이것은 소멸자와 생성자에 대해 요청할 때 완전히 다른 질문입니다.
만약 당신의 소멸자가 그렇다면 하워드가 지적한 것처럼virtual
그 차이는 무시할 만하다 . 그러나 소멸자가 가상 이 아닌 경우 완전히 다른 이야기입니다. 생성자도 마찬가지입니다.
= default
특수 멤버 함수 (기본 생성자, 복사 / 이동 생성자 / 할당, 소멸자 등)에 구문을 사용 한다는 것은 단순히하는 것과 매우 다른 의미 {}
입니다. 후자의 경우, 기능은 "사용자 제공"이됩니다. 그리고 그것은 모든 것을 바꿉니다.
이것은 C ++ 11의 정의에 의한 간단한 클래스입니다.
struct Trivial
{
int foo;
};
기본 생성을 시도하면 컴파일러에서 기본 생성자를 자동으로 생성합니다. 복사 / 이동 및 파괴도 마찬가지입니다. 사용자가 이러한 멤버 함수를 제공하지 않았으므로 C ++ 11 사양에서는이를 "사소한"클래스로 간주합니다. 따라서 memcpy처럼 내용을 초기화하는 등의 작업을 수행하는 것이 합법적입니다.
이:
struct NotTrivial
{
int foo;
NotTrivial() {}
};
이름에서 알 수 있듯이 이것은 더 이상 사소한 것이 아닙니다. 사용자가 제공하는 기본 생성자가 있습니다. 비어 있는지는 중요하지 않습니다. C ++ 11의 규칙에 관한 한, 이것은 사소한 유형이 될 수 없습니다.
이:
struct Trivial2
{
int foo;
Trivial2() = default;
};
이름에서 알 수 있듯이 이것은 사소한 유형입니다. 왜? 컴파일러에게 기본 생성자를 자동으로 생성하도록 지시했기 때문입니다. 따라서 생성자는 "사용자 제공"이 아닙니다. 따라서이 유형에는 사용자가 제공 한 기본 생성자가 없으므로 유형이 사소한 것으로 계산됩니다.
= default
구문은 같은 기능의 생성을 방지 멤버 함수를 추가 복사 생성자 / 지정, 같은 일을 주로있다. 그러나 컴파일러에서 특수 동작을 트리거하기 때문에 기본 생성자 / 소멸자에서도 유용합니다.
둘 다 사소하지 않습니다.
베이스와 멤버의 noexcept 사양에 따라 둘 다 동일한 noexcept 사양을 갖습니다.
The only difference I'm detecting so far is that if Widget
contains a base or member with an inaccessible or deleted destructor:
struct A
{
private:
~A();
};
class Widget {
A a_;
public:
#if 1
virtual ~Widget() = default;
#else
virtual ~Widget() {}
#endif
};
Then the =default
solution will compile, but Widget
won't be a destructible type. I.e. if you try to destruct a Widget
, you'll get a compile-time error. But if you don't, you've got a working program.
Otoh, if you supply the user-provided destructor, then things won't compile whether or not you destruct a Widget
:
test.cpp:8:7: error: field of type 'A' has private destructor
A a_;
^
test.cpp:4:5: note: declared private here
~A();
^
1 error generated.
The important difference between
class B {
public:
B(){}
int i;
int j;
};
and
class B {
public:
B() = default;
int i;
int j;
};
is that default constructor defined with B() = default;
is considered not-user defined. This means that in case of value-initialization as in
B* pb = new B(); // use of () triggers value-initialization
special kind of initialization that doesn't use a constructor at all will take place and for built-in types this will result in zero-initialization. In case of B(){}
this won't take place. The C++ Standard n3337 § 8.5/7 says
To value-initialize an object of type T means:
— if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
— if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T’s implicitly-declared default constructor is non-trivial, that constructor is called.
— if T is an array type, then each element is value-initialized; — otherwise, the object is zero-initialized.
For example:
#include <iostream>
class A {
public:
A(){}
int i;
int j;
};
class B {
public:
B() = default;
int i;
int j;
};
int main()
{
for( int i = 0; i < 100; ++i) {
A* pa = new A();
B* pb = new B();
std::cout << pa->i << "," << pa->j << std::endl;
std::cout << pb->i << "," << pb->j << std::endl;
delete pa;
delete pb;
}
return 0;
}
possible result:
0,0
0,0
145084416,0
0,0
145084432,0
0,0
145084416,0
//...
'programing tip' 카테고리의 다른 글
GUI를 단위 테스트하려면 어떻게해야합니까? (0) | 2020.06.12 |
---|---|
보유 할 수있는 JSON의 양에는 제한이 있습니까? (0) | 2020.06.12 |
오류 발생 ( 'msg') vs 새 오류 발생 ( 'msg') (0) | 2020.06.12 |
이 확인란은 어떻게 작동하며 어떻게 사용합니까? (0) | 2020.06.12 |
HTML : 선택적인 닫기 태그를 포함 또는 제외 하시겠습니까? (0) | 2020.06.12 |