문제

직접 구현하지 않으면 컴파일러가 때때로 기본 사본 생성자를 제공한다는 것을 알고 있습니다. 이 생성자가 정확히 무엇을하는지 혼란스러워합니다. 다른 객체가 포함 된 클래스가있는 경우, 그 중 신고 된 사본 생성자가없는 경우 동작은 무엇입니까? 예를 들어, 다음과 같은 클래스 :

class Foo {
  Bar bar;
};

class Bar {
  int i;
  Baz baz;
};

class Baz {
  int j;
};

이제 내가 이것을한다면 :

Foo f1;
Foo f2(f1);

기본 카피 생성자는 무엇을합니까? 컴파일러 생성 카피 생성자가 Foo 컴파일러 생성 생성자를 호출하십시오 Bar 복사합니다 bar, 그런 다음 컴파일러 생성 사본 생성자를 호출합니다. Baz?

도움이 되었습니까?

해결책

Foo f1;
Foo f2(f1);

예, 이것은 당신이 기대하는 것을 할 것입니다.
f2 사본 생성자 foo :: foo (foo const &)가 호출됩니다.
이 사본은 기본 클래스를 구성한 다음 각 멤버 (재귀 적으로)를 구성합니다.

다음과 같은 클래스를 정의하는 경우 :

class X: public Y
{
    private:
        int     m_a;
        char*   m_b;
        Z       m_c;
};

다음 방법은 컴파일러에 의해 정의됩니다.

  • 생성자 (기본값) (2 버전)
  • 생성자 (사본)
  • 소멸자 (기본값)
  • 과제 연산자

생성자 : 기본값 :

실제로 두 개의 기본 생성자가 있습니다.
하나는 사용됩니다 zero-initialization 다른 하나는 사용됩니다 value-initialization. 중고는 사용 여부에 따라 다릅니다 () 초기화 중지 여부.

// Zero-Initialization compiler generated constructor
X::X()
    :Y()                // Calls the base constructor
                        //     If this is compiler generated use 
                        //     the `Zero-Initialization version'
    ,m_a(0)             // Default construction of basic PODS zeros them
    ,m_b(0)             // 
    m_c()               // Calls the default constructor of Z
                        //     If this is compiler generated use 
                        //     the `Zero-Initialization version'
{
}

// Value-Initialization compiler generated constructor
X::X()
    :Y()                // Calls the base constructor
                        //     If this is compiler generated use 
                        //     the `Value-Initialization version'
    //,m_a()            // Default construction of basic PODS does nothing
    //,m_b()            // The values are un-initialized.
    m_c()               // Calls the default constructor of Z
                        //     If this is compiler generated use 
                        //     the `Value-Initialization version'
{
}

참고 : 기본 클래스 또는 멤버에 유효한 표시 기본 생성자가없는 경우 기본 생성자를 생성 할 수 없습니다. 코드가 기본 생성자를 사용하려고 시도하지 않는 한 오류가 아닙니다 (그런 다음 컴파일 시간 오류 만).

생성자 (사본)

X::X(X const& copy)
    :Y(copy)            // Calls the base copy constructor
    ,m_a(copy.m_a)      // Calls each members copy constructor
    ,m_b(copy.m_b)
    ,m_c(copy.m_c)
{}

참고 : 기본 클래스 또는 멤버에 유효한 가시 카피 생성자가없는 경우 카피 생성자를 생성 할 수 없습니다. 코드가 사본 생성자를 사용하려고 시도하지 않는 한 오류가 아닙니다 (그런 다음 컴파일 시간 오류 만).

과제 연산자

X& operator=(X const& copy)
{
    Y::operator=(copy); // Calls the base assignment operator
    m_a = copy.m_a;     // Calls each members assignment operator
    m_b = copy.m_b;
    m_c = copy.m_c;

    return *this;
}

참고 : 기본 클래스 또는 멤버에 유효한 실행 가능한 할당 연산자가없는 경우 할당 연산자를 생성 할 수 없습니다. 코드가 할당 연산자를 사용하려고 시도하지 않는 한 오류가 아닙니다 (그런 다음 컴파일 시간 오류 만).

폐물 소각로

X::~X()
{
                        // First runs the destructor code
}
    // This is psudo code.
    // But the equiv of this code happens in every destructor
    m_c.~Z();           // Calls the destructor for each member
    // m_b              // PODs and pointers destructors do nothing
    // m_a          
    ~Y();               // Call the base class destructor
  • 만약에 어느 생성자 (사본 포함)가 선언 된 다음 기본 생성자는 컴파일러에 의해 구현되지 않습니다.
  • 카피 생성자가 선언되면 컴파일러가 하나를 생성하지 않습니다.
  • 할당 연산자가 선언되면 컴파일러가 하나를 생성하지 않습니다.
  • 소멸자가 선언되면 컴파일러는 컴파일러가 하나를 생성하지 않습니다.

코드를보고 다음 사본 생성자가 생성됩니다.

Foo::Foo(Foo const& copy)
    :bar(copy.bar)
{}

Bar::Bar(Bar const& copy)
    :i(copy.i)
    ,baz(copy.baz)
{}

Baz::Baz(Baz const& copy)
    :j(copy.j)
{}

다른 팁

컴파일러는 귀하가 아닌 한 사본 생성자를 제공합니다 선언하다 (참고 : 아닙니다 정의하다) 하나 자신. 컴파일러 생성 카피 생성자는 단순히 클래스의 각 구성원 (및 각 기본 클래스)의 사본 생성자를 호출합니다.

과제 연산자와 파괴자 BTW에 대해서도 마찬가지입니다. 그러나 기본 생성자와는 다릅니다. 다른 생성자를 직접 선언하지 않는 경우에만 컴파일러가 제공합니다.

예, 컴파일러 생성 카피 생성자는 멤버가 포함 된 클래스에서 선언 된 순서대로 멤버 별 사본을 수행합니다. 멤버 유형 중 하나가 카피 생성자를 제공하지 않으면 포함 된 클래스의 사본 생성자를 생성 할 수 없습니다. 아마도 다른 생성자 중 하나를 사용하여 카피로 구성 할 수없는 멤버의 값을 초기화하기 위해 적절한 수단을 결정할 수 있다면 수동으로 하나를 작성할 수 있습니다.

C ++ 기본 사본 생성자 a 얕은 복사. 얕은 사본은 원래 객체가 참조 할 수있는 새 개체 사본을 만들지 않습니다. 구형 및 새로운 개체는 단순히 동일한 메모리 위치에 대한 독특한 포인터를 포함합니다.

컴파일러는 필요한 생성자를 생성합니다.

그러나 카피 건설자를 직접 정의하자마자 컴파일러는 해당 클래스에 대해 무엇이든 생성을 포기하고 적절한 생성자가 정의되어 있지 않으면주고 오류가 발생합니다.

예제 사용 :

class Baz {
    Baz(const Baz& b) {}
    int j;
};
class Bar {
    int i;
    Baz baz;
};
class Foo {
    Bar bar;
};

BAZ가 카피 구성 가능하지 않고 컴파일러가 FOO의 기본값 및 복사 Corpetoctor를 생성 할 수 없기 때문에 기본 인스턴스화 또는 카피 구성 FOO를 시도하면 오류가 발생합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top