IT박스

C ++에 암시 적 기본 생성자가 있습니까?

itboxs 2020. 11. 26. 08:05
반응형

C ++에 암시 적 기본 생성자가 있습니까?


지금 읽고있는 책 ( C ++ Without Fear )에서 클래스에 대한 기본 생성자를 선언하지 않으면 컴파일러가 "각 데이터 멤버를 0으로 만드는"생성자를 제공한다고 말합니다. 나는 이것을 실험 해 보았고 어떤 제로화 동작도 보지 못했습니다. Google에서도 이에 대해 언급 한 내용을 찾을 수 없습니다. 이것은 단지 오류입니까 아니면 특정 컴파일러의 기이 한 것입니까?


생성자를 정의하지 않으면 컴파일러가 기본 생성자를 정의합니다.

이것의 구현

기본 생성자는 다음과 같습니다.

  • 기본은 기본 클래스를 생성합니다 (기본 클래스에 기본 생성자가 없으면 컴파일 실패입니다).
  • default는 선언 순서대로 각 멤버 변수를 구성합니다. (멤버에 기본 생성자가 없으면 컴파일 실패입니다.)

참고 :
POD 데이터 (int, float, pointer 등)에는 명시 적 생성자가 없지만 기본 동작은 아무것도하지 않는 것입니다 (C ++ 철학의 관점에서, 명시 적으로 요청하지 않는 한 비용을 지불하고 싶지 않습니다. 그것).

소멸자 / 복사 생성자 / 할당 연산자가 정의되지 않은 경우 컴파일러는 그 중 하나를 빌드합니다 (따라서 클래스에는 항상 소멸자 / 복사 생성자 / 할당 연산자가 있습니다 (속임수를 사용하고 명시 적으로 선언하지만 정의하지 않는 경우)).
기본 구현은 다음과 같습니다.

폐물 소각로:

  • 사용자 정의 소멸자가 정의 된 경우 제공된 코드를 실행합니다.
  • 선언의 역순으로 각 멤버의 소멸자를 호출합니다.
  • 기본 클래스의 소멸자를 호출합니다.

복사 생성자 :

  • 기본 클래스 복사 생성자를 호출합니다.
  • 선언 순서대로 각 멤버 변수에 대한 복사 생성자를 호출합니다.

할당 연산자 :

  • 기본 클래스 할당 연산자를 호출하십시오.
  • 선언 순서대로 각 멤버 변수의 할당 연산자를 호출합니다.
  • 이것에 대한 참조를 반환합니다.

참고 POD 데이터의 복사 구성 / 할당 연산자는 데이터를 복사하는 것입니다 (따라서 RAW 포인터와 관련된 얕은 복사 문제).


생성자를 제공 하지 않으면 기본 생성자가 컴파일러에 의해서만 생성된다는 점을 지적 할 가치가 있다고 생각합니다 . 즉, 인수를받는 생성자를 하나만 제공하면 컴파일러가 인수가 없는 기본 생성자를 생성 하지 않습니다 .

책에서 말하는 제로화 동작은 아마도 특정 컴파일러에 따라 다릅니다. 나는 항상 그것이 다를 수 있고 모든 데이터 멤버를 명시 적으로 초기화해야한다고 가정했습니다.


  • 컴파일러가 기본 생성자를 자동으로 생성합니까?
  • 암시 적으로 생성 된 기본 생성자가 제로 초기화를 수행합니까?

2003 표준의 언어를 합법적으로 구문 분석하는 경우 대답은 yesno 입니다. 그러나 이것은 사용자 정의 기본 생성자와 달리 처음부터 개체를 만들 때 암시 적으로 정의 된 기본 생성자가 항상 사용되는 것은 아니기 때문에 전체 이야기 가 아닙니다. 두 가지 다른 시나리오가 있습니다 : 생성 없음멤버 별 값 초기화 .

"구성 없음"사례는 기능적으로 사소한 기본 생성자를 호출하는 것과 다르지 않기 때문에 실제로는 기술적 인 부분입니다 . [명시 적으로 인수가없는 생성자를 호출하는 것처럼]을 "()"회원이 많다는 가치 초기화 사용하여 호출되고 : 다른 경우는 더 흥미 롭다 는 기술적이라 무엇을 우회 기본 생성자 . 대신 각 데이터 멤버에 대해 값 초기화를 재귀 적으로 수행하고 기본 데이터 유형의 경우 이는 궁극적으로 0 초기화로 해결됩니다 .

따라서 실제로 컴파일러는 암시 적으로 정의 된 두 가지 기본 생성자를 제공 합니다. 그중 하나는 기본 멤버 데이터의 0 초기화를 수행하고 다른 하나 수행하지 않습니다. 다음은 각 생성자 유형을 호출하는 방법에 대한 몇 가지 예입니다.

    MyClass a; // default-construction or no construction
    MyClass b = MyClass(); // member-wise value-initialization

    new MyClass; // default-construction or no construction
    new MyClass(); // member-wise value-initialization

참고 : 사용자가 선언 한 기본 생성자 존재하는 경우 멤버 별 값 초기화는 단순히이를 호출하고 중지합니다.


여기에 표준이 이것에 대해 말하는 것에 대한 다소 자세한 분석이 있습니다.

  • 생성자를 선언하지 않으면 컴파일러는 암시 적으로 기본 생성자를 만듭니다 [12.1-5]

  • 기본 생성자 기본 유형을 초기화 하지 않습니다. [12.1-7]

    MyClass() {} // implicitly defined constructor
    
  • "()"로 객체를 초기화하면 기본 생성자를 직접 호출하지 않습니다. 대신, 값-초기화 (value-initialization ) 라고하는 긴 일련의 규칙을 유발합니다 [8.5-7]

  • 값 초기화의 결과 는 암시 적으로 선언 된 기본 생성자가 호출되지 않는다는 것 입니다. 대신, 재귀 멤버 별 값 초기화가 호출되어 궁극적으로 모든 기본 멤버를 0으로 초기화 하고 사용자가 선언 한 생성자가있는 모든 멤버에 대해 기본 생성자를 호출합니다. [8.5-5]

  • 값 초기화는 기본 유형에도 적용되며 0으로 초기화됩니다. [8.5-5]

    a = int(); // equivalent to int a=0;
    

이 모든 것은 대부분의 목적을 위해 정말로 논쟁의 여지가 있습니다. 클래스 작성자는 일반적으로 암시 적 초기화 시퀀스 중에 데이터 멤버가 제로화 될 것이라고 가정 할 수 없으므로 자체 관리 클래스에 초기화가 필요한 기본 데이터 멤버가있는 경우 자체 생성자를 정의해야합니다.

그렇다면 이것이 언제 중요합니까?

  • 제네릭 코드가 알 수없는 유형의 초기화를 강제하려는 상황이있을 수 있습니다. 가치 초기화는이를위한 방법을 제공합니다. 사용자가 생성자를 제공 한 경우 암시 적 제로 초기화가 발생하지 않는다는 점을 기억하십시오.

  • 기본적으로 std :: vector에 포함 된 데이터는 값으로 초기화됩니다. 이렇게하면 메모리 디버거가 초기화되지 않은 메모리 버퍼와 관련된 논리 오류를 식별하는 것을 방지 할 수 있습니다.

    vector::resize( size_type sz, T c=T() ); // default c is "value-initialized"
    
  • 값 초기화 구문을 사용하여 기본 유형 또는 "일반 이전 데이터"(POD) 유형 구조의 전체 배열을 0으로 초기화 할 수 있습니다.

    new int[100]();
    

이 게시물 에는 표준 버전 간의 변형에 대한 자세한 내용 이 포함 되어 있으며 주요 컴파일러에서 표준이 다르게 적용되는 경우에 대해서도 언급합니다.


C ++는 기본 생성자를 생성하지만 사용자가 직접 생성하지 않은 경우에만 생성됩니다. 표준은 데이터 멤버를 0으로 만드는 것에 대해 아무것도 말하지 않습니다. 기본적으로 객체를 처음 생성 할 때는 정의되지 않습니다.

대부분의 C ++ 기본 유형에는 0으로 초기화하는 기본 "생성자"가 있지만 (int (), bool (), double (), long () ) 컴파일러가 호출하지 않기 때문에 혼란 스러울 수 있습니다 . 오브젝트 멤버와 마찬가지로 POD 멤버를 초기화합니다.

STL 이러한 생성자를 사용하여 기본 유형을 보유하는 컨테이너의 콘텐츠를 기본 구성 한다는 점은 주목할 가치가 있습니다. STL 컨테이너의 항목이 초기화되는 방법에 대한 자세한 내용 이 질문살펴볼 수 있습니다 .


클래스에 대해 생성 된 기본 생성자는 내장 유형을 초기화하지 않지만 모든 사용자 정의 멤버에서 기본 생성자를 호출합니다.

class Foo
{
public:
     int x;
     Foo() : x(1) {}
};

class Bar
{
public:
     int y;
     Foo f;
     Foo *fp;
};

int main()
{

    Bar b1; 
    ASSERT(b1.f.x == 1); 
    // We know nothing about what b1.y is set to, or what b1.fp is set to.

    // The class members' initialization parallels normal stack initialization.
    int y;  
    Foo f; 
    Foo *fp; 
    ASSERT(f.x == 1);
    // We know nothing about what y is set to, or what fp is set to.

}

컴파일러는 사용자가 만든 생성자가없는 경우 기본 생성자와 소멸자를 생성합니다. 이는 데이터 멤버의 상태를 수정하지 않습니다.

C ++ (및 C)에서는 할당 된 데이터의 내용이 보장되지 않습니다. 디버그 구성에서 일부 플랫폼은 버그를 식별하는 데 도움이되도록이 값을 알려진 값 (예 : 0xFEFEFEFE)으로 설정하지만이 값에 의존해서는 안됩니다.


Zero-ing out only occurs for globals. So if your object is declared in the global scope, its members will be zero-ed out:

class Blah
{
public:
    int x;
    int y;
};

Blah global;

int main(int argc, char **argv) {
    Blah local;
    cout<<global.x<<endl;  // will be 0
    cout<<local.x<<endl;   // will be random
}

C++ does not guarantee zeroing out memory. Java and C# do (in a manner of speaking).

Some compilers might, but don't depend on that.


In C++11, a default constructor generated by the compiler is marked deleted , if :

  • the class has a reference field
  • or a const field without a user-defined default constructor
  • or a field without a default initializer, with a deleted default constructor

http://en.cppreference.com/w/cpp/language/default_constructor


C++ generates a default constructor. If needed (determined at compile time I believe), it will also generate a default copy constructor and a default assignment constructor. I haven't heard anything about guarantees for zeroing memory though.


The compiler by default will not be generating the default constructor unless the implementation does not require one . So , basically the constructor has to be a non-trivial constructor.

For constructor to be non-trivial constructor, following are the conditions in which any one can suffice:

1) The class has a virtual member function. 2) Class member sub-objects or base classes have non-trivial constructors. 3) A class has virtual inheritance hierarchy.

참고URL : https://stackoverflow.com/questions/563221/is-there-an-implicit-default-constructor-in-c

반응형