default_constructor — 기본 생성자
default_constructor — 기본 생성자
**기본 생성자(default constructor)**는 인자 없이 호출될 수 있는 생성자예요. 객체를 만들 때 초기화 인자를 전달하지 않아도 호출되는 생성자죠.
예를 들어 std::vector<int> v;처럼 인자 없이 객체를 만들면 기본 생성자가 불려요. 필요하면 기본값을 주는 매개변수로 기본 생성자를 만들 수도 있어요.
출처: cppreference
본문
기본 생성자는 인자 없이 호출될 수 있는 생성자예요.
문법 (Syntax)
class-name ( parameter-list ) ;
class-name ( parameter-list ) function-body
class-name () = default;
class-name ( parameter-list ) = delete;
class-name :: class-name ( parameter-list ) function-body
class-name :: class-name () = default;
class-name— 기본 생성자를 선언하는 클래스parameter-list— 모든 매개변수가 기본 인자를 가진 매개변수 목록function-body— 기본 생성자의 함수 본문
- 클래스 정의 안에서의 기본 생성자 선언 2-4. 클래스 정의 안에서의 기본 생성자 정의. 3은 명시적으로 default 처리, 4는 삭제된 생성자 5,6. 클래스 정의 밖에서의 기본 생성자 정의(클래스는 1의 선언을 포함해야 함). 6은 명시적으로 default 처리
기본 생성자는 기본 초기화(default initialization)와 값 초기화(value initialization) 중에 호출돼요.
암시적으로 선언된 기본 생성자
클래스 타입에 사용자 선언 생성자나 생성자 템플릿이 없으면, 컴파일러는 기본 생성자를 그 클래스의 inline public 멤버로 암시적으로 선언해요.
암시적으로 선언된(또는 첫 선언에서 default 처리된) 기본 생성자는 동적 예외 명세/noexcept 명세에 설명된 예외 명세를 가져요.
암시적으로 정의된 기본 생성자
생성자가 삭제된 것으로 정의되지 않았다면, 컴파일러가 ODR-사용(odr-used)되거나 상수 평가에 필요할 때 기본 생성자를 암시적으로 정의해요.
암시적으로 정의된 기본 생성자는 빈 본문과 빈 초기화 목록을 가진 사용자 정의 생성자와 같은 효과를 가져요. 즉, 이 클래스의 기반 클래스와 비정적 멤버의 기본 생성자를 호출해요. 빈 사용자 제공 생성자를 가진 클래스 타입은 값 초기화 중에 암시적으로 정의된 기본 생성자를 가진 것과 다르게 취급될 수 있어요.
C++11부터, 이에 해당하는 요구 사항이 충족되면 생성된 생성자는 constexpr이 돼요. 사용자 정의 생성자가 이미 있더라도 default 키워드로 컴파일러가 기본 생성자를 자동 생성하게 강제할 수 있어요.
삭제된 기본 생성자
클래스 T에 대해 암시적으로 선언되거나 명시적으로 default 처리된 기본 생성자는 다음 조건 중 하나라도 만족하면 삭제된 것으로 정의돼요.
T가 기본 초기화자가 없는 참조 타입의 비정적 데이터 멤버를 가질 때T가 기본 멤버 초기화자가 없는 const 한정 타입의 비변형(non-variant) 비정적 데이터 멤버를 가질 때- (C++26까지)
T가 유니언이고 모든 변형 멤버가 const 한정 타입일 때 - (C++26까지)
T가 비유니온 클래스이고 익명 유니언 멤버의 모든 멤버가 const 한정 타입일 때 T가 삭제되거나 기본 생성자에서 접근할 수 없는 소멸자를 가진 클래스 타입의 부분 객체를 가질 때
사용자 정의 생성자가 없고 암시적으로 선언된 기본 생성자가 trivial하지 않다면, delete 키워드로 컴파일러가 기본 생성자의 자동 생성을 막을 수 있어요.
Trivial 기본 생성자
클래스 T의 기본 생성자는 다음 조건을 모두 만족하면 trivial이에요.
- 생성자가 암시적으로 선언되었고 사용자 제공이 아닐 때
T가 가상 멤버 함수가 없을 때T가 가상 기반 클래스가 없을 때- (C++11부터)
T가 기본 초기화자를 가진 비정적 멤버가 없을 때 T의 모든 직접 기반이 trivial 기본 생성자를 가질 때- (C++26까지) 클래스 타입의 모든 비정적 멤버(또는 그 배열)가 trivial 기본 생성자를 가질 때
Trivial 기본 생성자는 아무 동작도 수행하지 않는 생성자예요. C 언어와 호환되는 모든 데이터 타입(POD 타입)은 trivially default-constructible이에요.
예제 (Example)
struct A
{
int x;
A(int x = 1): x(x) {} // 사용자 정의 기본 생성자
};
struct B : A
{
// B::B() 는 암시적으로 정의됨, A::A() 호출
};
struct C
{
A a;
// C::C() 는 암시적으로 정의됨, A::A() 호출
};
struct D : A
{
D(int y) : A(y) {}
// 다른 생성자가 존재하므로 D::D() 는 선언되지 않음
};
struct E : A
{
E(int y) : A(y) {}
E() = default; // 명시적으로 default 처리, A::A() 호출
};
struct F
{
int& ref; // 참조 멤버
const int c; // const 멤버
// F::F() 는 암시적으로 삭제된 것으로 정의됨
};
struct G
{
G(const G&) {}
// G::G() 는 암시적으로 삭제된 것으로 정의됨
};
struct H
{
H(const H&) = delete;
// H::H() 는 암시적으로 삭제된 것으로 정의됨
};
struct I
{
I(const I&) = default;
// I::I() 는 암시적으로 삭제된 것으로 정의됨
};
int main()
{
A a;
B b;
C c;
// D d; // 컴파일 오류
E e;
// F f; // 컴파일 오류
// G g; // 컴파일 오류
// H h; // 컴파일 오류
// I i; // 컴파일 오류
}
이 예제의 핵심은, 사용자 선언 복사 생성자(제공되든 삭제되든 default 처리되든)가 기본 생성자의 암시적 생성을 막는다는 점이에요. 그래서 G, H, I는 기본 생성자가 없는 것으로 취급되고, 참조·const 멤버를 가진 F 역시 기본 생성자를 만들 수 없어요.