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 |