프로그래밍/C++

[C++] 생성자 (constructor)

갓똥 2019. 10. 31. 00:10
728x90
반응형

1. 생성자 (constructor)

#include <iostream>
using namespace std;

class Point {
    int x, y;
public:
    Point()             { x = 0; y = 0; cout << "1" << endl; }
    Point(int a, int b) { x = a; y = b; cout << "2" << endl; }
};

int main() {
    Point p1;
    Point p2(1, 2);
}

  ① 생성자를 사용하는 이유

    => 객체를 자동으로 초기화하기 위해서

  ② 생성자 모양

    => 클래스 이름과 동일한 함수

    => 리턴 타입을 표기하지 않는다.

    => 인자는 있어도 되고 없어도 된다. - 2개 이상 만들 수 있다.

  ③ 객체를 생성하면

    => 객체의 크기 만큼 메모리를 할당하고

    => 생성자가 호출된다.

    => 생성자가 없으면 객체를 만들 수 없다.

  디폴트 생성자

    => 사용자가 생성자를 하나도 만들지 않으면 컴파일러가 인자 없는 생성자를 제공해준다.

 


2. 객체를 생성하는 다양한 방법

#include <iostream>
using namespace std;

class Point {
    int x, y;
public:
    Point()             { x = 0; y = 0; cout << "1" << endl; }
    Point(int a, int b) { x = a; y = b; cout << "2" << endl; }
};

int main() {
    Point p1(1, 2);    // 2
    Point p2{1, 2};    // 2
    Point p3 = {1, 2}; // 2
    
    Point p4;      // 1
    Point p5();    // x
    Point p6{};    // 1
    Point p7 = {}; // 1
    
    Point p8[3];                     // 1 1 1
    Point p9[3] = {Point(1, 1)};     // 2 1 1
    Point p10[3] = {{1, 1}, {2, 2}}; // 2 2 1
    
    Point* p11; // x
    
    p11 = static_cast<Point*>( malloc(sizeof(Point))); // x
    free(p11);
    
    p11 = new Point; // 1
    delete p11;
    
    p11 = new Point(); // 1
    delete p11;
    
    p11 = new Point(1, 2); // 2
    delete p11;
}

  ① () 또는 {}를 사용해서 생성자 인자를 전달한다.

   직접 초기화(direct initialization)복사 초기화(copy initialization)

    - p1 : Point(int a, int b)를 호출

    - p2 : Point(int a, int b)를 호출 // 일괄된 초기화 C++11부터 가능 - 직접 초기화

    - p3 : Point(int a, int b)를 호출 // 일괄된 초기화 C++11부터 가능 - 복사 초기화

 

    - p4 : Point()를 호출 // 인자 없는 초기화

    - p5 : 반환타입 이름(); // 객체 생성이 아닌 함수 선어문

    - p6 : Point()를 호출 // 인자 없는 일관된 초기화 C++11부터 가능 - 직접 초기화

    - p7 : Point()를 호출 // 인자 없는 일관된 초기화 C++11부터 가능 - 복사 초기화

 

   배열 생성 => 배열의 개수 만큼 생성자가 호출된다.

    - p8 : Point()를 호출 // 3개짜리 배열로 메모리에 객체가 3번 놓임으로 생성자를 3번 호출

    - p9 : Point(int a, int b) 1번, Point() 2번 호출 // 위와 같이 배열을 만드는데 첫번째는 Point(int a, int b)를 넣겠다.

    - p10 : Point(int a, int b) 2번, Point() 1번 호출 // 일괄된 초기화 C++11부터 가능

 

  ④ malloc vs new

  1. Point* p11; - 객체 생성이 아닌 포인터 생성 / 생성자 호출 안됨
  2. p11 = static_cast<Point*>( malloc(sizeof(Point))); - malloc으로 생성 -> 메모리 공간만 잡음 / 생성자 호출 안됨
  3. p11 = new Point; - 메모리 할당 및 생성자 호출 / 1번 생성자 호출
  4. p11 = new Point(); - 메모리 할당 및 생성자 호출 / 1번 생성자 호출
  5. p11 = new Point(1, 2); - 메모리 할당 및 생성자 호출 / 2번 생성자 호출

3. 생성자 / 소멸자 호출 순서

#include <iostream>

class Point {
    int x, y;
public:
    Point()  { std::cout << "Point()"  << std::enld; }
    ~Point() { std::cout << "~Point()" << std::endl; }
};

class Rect {
    Point p1;
    Point p2;
public:
    Rect()  { std::cout << "Rect()"  << std::endl; }
    ~Rect() { std::cout << "~Rect()" << std::endl; }
};

int main() {
    Rect r;
}

  ① 객체가 생성되면

    => 멤버의 생성자가 먼저 호출되고

    => 자신의 생성자가 호출된다.

  ② 객체가 파괴되면

    => 자신의 소멸자가 먼저 호출되고

    => 멤버의 소멸자가 호출된다.

 


4. 위임 생성자 (delegate constructor)

class Point {
    int x, y;
public:
    Point() : Point(0, 0) {
        x = 0;
        y = 0;
    }
    Point(int a, int b) {
        x = a;
        y = b;
    }
};

int main() {
    Point p;
}

  ① 생성자에서 다른 생성자를 호출하는 문법

    => C++11부터 지원하는 문법

    => 클래스의 구현부에 표기한다.

 


5. default constructor, delete constructor 

class Point {
    int x;
    int y;
public:
    // Point() {}
    Point() = default;
    // Point() = delete;
    Point(int a, int b) {}
};

int main() {
    Point p1;
    Point p2(1, 2);
}

  ① Point() = default;

    => 컴파일러에게 디폴트 생성자를 만들어 달라는 문법

    => 클래스 선언부에만 표기하면 되고 구현부는 만들지 않아도 된다.

  ② Point() = delete;

    => 함수 삭제로, 기본 생성자에서는 잘 쓰이지 않고

    => 복사 생성자에서는 쓰임

728x90
반응형