devdw
bloom_
devdw
전체 방문자
오늘
어제
  • 분류 전체보기 (20)
    • develop (15)
      • 개발기록 (0)
      • Java (5)
      • C++ (4)
      • Spring (0)
      • Database (3)
      • Algorithm (1)
      • etc (2)
    • diary (3)
      • 일기 (0)
      • 🍕🍔🍟 (1)
      • Review (2)
    • works (1)
      • reviews (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 다이소
  • Share
  • class
  • STAEDTLER NORIS DIGITAL S PAN
  • iteration
  • SourceCode
  • java
  • Codility
  • 길벗
  • 코딩테스트
  • 변수
  • 스테들러
  • 머신러닝
  • github
  • AI
  • array
  • database
  • 신경망 교과서
  • float
  • GIST
  • 신경망
  • 순간접착제
  • 조심또조심
  • PYTHON
  • 펜그립
  • 스테들러노리스디지털펜
  • 알고리즘
  • 난수생성
  • lesson1
  • xor

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
devdw

bloom_

[씹어먹는 C++ - 4-3, 4] 복사 생성자, 소멸자, const, static
develop/C++

[씹어먹는 C++ - 4-3, 4] 복사 생성자, 소멸자, const, static

2021. 9. 14. 16:59

4-3

malloc vs new

모두 동적으로 할당한다

  • new
    • 객체를 동적으로 생성 + 자동으로 생성자도 호출
  • malloc
    • 메모리 동적 할당만 함
 int main()
{
    Marine *marines[100];

    // 동적으로 메모리 할당
    marines[0] = new Marine(2, 3);
    marines[1] = new Marine(3, 5);

    marines[0]->show_status();
    marines[1]->show_status();

    std::cout << std::endl
              << "마린 1이 마린 2ㅣ 공격!" << std::endl;
    marines[1]->be_attacked(marines[0]->attack());
    marines[0]->show_status();
    marines[1]->show_status();

    // 동적 할당한 메모리 해제
    delete marines[0];
    delete marines[1];
}

소멸자 (Destructor)

생성한 객체가 소멸될 때 자동으로 호출되는 함수

~클래스이름()

디폴트 소멸자

소멸자가 필요없는 클래스에 기본으로 생기는 소멸자

Example

#include <iostream>
#include <string.h>
class Marine
{
    int hp;               // 체력
    int coord_x, coord_y; // 위치
    int damage;           // 공격력
    bool is_dead;
    char *name; // 마린 이름

public:
    Marine();                                      //default constructor
    Marine(int x, int y);                          // x, y 좌표에 마린 생성
    Marine(int x, int y, const char *marine_name); // 마린 이름까지 지정
    ~Marine();                                     // 소멸자

    int attack();                      // 데이미 입히기
    void be_attacked(int damage_earn); //얻은 데미지
    void move(int x, int y);           // 위치 이동

    void show_status(); // 마린 상태 보여주기
};
...
Marine::~Marine()
{
    std::cout << name << " 의 소멸자 호출!" << std::endl;
    if (name != NULL)
    {
        delete[] name; // 이름 메모리도 소멸
    }
}

복사 생성자 (copy constructor)

// 클래스이름 T
T(const T& a);

다른 T의 객체 a를 상수 레퍼런스로 받음

  • const 이기 때문에 복사 생성자 내부에서 a 데이터를 변경할 수 없음
  • 복사만 가능
  • 인자로 받는 변수의 내용을 함수 내부에서 바꾸지 않는다면 const를 붙여주기!
  • 복사 생성자는 생성 시에만 호출됨

실습

#include <iostream>

class Study_Copy_Con
{
    int a;

public:
    Study_Copy_Con();
    Study_Copy_Con(int tmp);
    Study_Copy_Con(const Study_Copy_Con &scc);
    void show_status();
};
Study_Copy_Con::Study_Copy_Con()
{
    a = 0;
}
Study_Copy_Con::Study_Copy_Con(int tmp)
{
    a = tmp;
}
Study_Copy_Con::Study_Copy_Con(const Study_Copy_Con &scc)
{
    std::cout << "복사 생성자 호출!" << this << std::endl;
    a = scc.a;
}
void Study_Copy_Con::show_status()
{
    std::cout << "주소: " << this << std::endl;
    std::cout << "a: " << a << std::endl;
}

int main()
{

    Study_Copy_Con scc1(1);
    Study_Copy_Con scc2(scc1);
    Study_Copy_Con scc3 = scc2; // 복사 생성자 한 번 호출
    Study_Copy_Con scc4;
    scc4 = scc3; // 생성자 한 번 호출되고 해당 명령 실행

    scc1.show_status();
    scc2.show_status();
    scc3.show_status();
    scc4.show_status();
}

실습 결과

디폴트 복사 생성자

대응하는 원소들을 1대1로 복사해주는 기본 복사 생성자가 존재함

한계

클래스 내에 char* name 과 같은 메모리를 동적할당하여 저장하는 문자열 배열이 있다고 가정하자.
디폴트 복사 생성자를 사용하면 아래와 같은 일이 벌어질 수 있다. (같은 공간을 가리킴)


사용할 땐 문제가 생기지 않지만, pc1을 소멸시켰을 때, name 공간도 소멸자에 의해 메모리 해제 되기 때문에 pc2를 소멸시킬 때 name 공간을 또 해제 시키게 된다. -> 문제 발생!!

해결방안

복사 생성자에서 name을 그대로 복사하지 않고, 다른 메모리에 동적할당 해서 해당 내용만 복사하도록 한다.
deep copy가 필요할 땐 사용자가 직접 복사 생성자를 만들어야 한다.

  • deep copy : 메모리를 새로 할당해서 내용을 복사하는 것
  • shallow copy : 메모리를 할당하지 않고 단순히 대입만 해주는 것
    class Test
    {
      char *name;
      Test(char *n);
      Test(const Test &t);
    };
    Test::Test(char *n)
    {
      name = new char[strlen(n) + 1];
      strcpy(name, n);
    }
    Test::Test(const Test &t)
    {
      name = new char[strlen(t.name) + 1];
      strcpy(name, t.name);
    }

4-4

초기화 리스트

생성자 호출과 동시에 멤버 변수들을 초기화함

  • var1과 arg1의 이름은 같아도 됨

    생성자이름 :var1(arg1), var2(arg2){}
  • 기존 생성자와의 차이점

    • 초기화리스트

      • 복사 생성자 호출
      • 생성과 초기화를 동시에 함
        int a = 10;
    • 초기화리스트 사용 X

      • 디폴트 생성자 호출된 뒤 대입 수행됨
      • 생성을 먼저한 후 그 다음에 대입함
        int a;
        a = 10;
        초기화 리스트가 필요한 곳
  • 레퍼런스, 상수

  • 클래스 내부에 레퍼런스 변수나 상수를 넣는다면 생성자에서 무조건 초기화 리스트를 사용해서 초기화 해야함

static

  • 멤버 변수
    클래스의 모든 객체들이 공유하는 변수
  • 정의와 동시에 값이 자동으로 초기화 됨
  • 클래스 내부에서 초기화할 수 없음
    • 클래스 내부에서 초기화할 수 있는 경우는 const static 변수 만 가능
  • 함수
    클래스 전체에 딱 한 개 존재하는 함수
  • 객체 없이도 클래스 자체에서 호출할 수 있게 됨
  • (클래스명)::(static함수) 로 호출함

this

자기 자신을 가리키는 포인터

const 함수

변수들의 값을 바꾸지 않고 읽기만 하는 멤버 함수

(기존 함수 정의) const;
// example
class Marine
{
    ...
    int attack() const;
    ...
};
int Marine::attack const {return default_damage;}

'develop > C++' 카테고리의 다른 글

[씹어먹는 C++ - 4-1, 2] 객체지향 프로그래밍, 함수 오버로딩, 생성자  (0) 2021.09.01
[씹어먹는 C++ - 3] 메모리 할당/해제  (0) 2021.09.01
[씹어먹는 C++ - 2] 참조자  (0) 2021.09.01
    'develop/C++' 카테고리의 다른 글
    • [씹어먹는 C++ - 4-1, 2] 객체지향 프로그래밍, 함수 오버로딩, 생성자
    • [씹어먹는 C++ - 3] 메모리 할당/해제
    • [씹어먹는 C++ - 2] 참조자
    devdw
    devdw
    끄적끄적

    티스토리툴바