본문 바로가기
개발/C++

11장 포인터와 동적 메모리 관리(후)

by 민돌이2 2019. 5. 9.

한성대학교 김설현교수님 강의내용을 바탕으로 작성함

 

동적 메모리 할당프로그램 실행 도중 필요한 만큼의 메모리를 할당하는 것이다.new연산자를 이용해 동적으로 메모리를 할당하며, heap에 저장된다.

int *p = new int;

 

new연산자를 사용해 할당한 메모리는 영구적이며, delete를 사용하여 제거하고 포인터변수에 NULL을 대입해야한다.

int *p = new int;
delte p;
p = NULL;

int *p = new int[size];
delete [ ] p;
p = NULL;

 

동적 객체 생성과 접근

아래의 구문을 사용하여 heap에 동적으로 객체 생성 가능하다.

Circle* cp = new Circle;
Circle* cp = new Circle(2);

포인터를 통한 객체 멤버에 접근하기 위해서는 점(.)이나 화살표(->)연산자를 사용한다.

cp->getRadius()
(*cp).getRadius()

 

this 포인터

객체 자신을 가리킨다.

set()함수나 매개변수 있는 생성자에서 종종 매개변수와 데이터필드에 같은 이름을 사용할 때 사용한다.

Circle::Circle(double radius)
{
	this->radius = radius; //this->radius 는 본래의 radius이고 오른쪽의 radius는 받는 값
}

 

소멸자

생성자의 반대이며 생성자와 동일한 이름을 갖지만 앞에(~)가 붙어야 한다.

기본적으로 모든 클래스에는 기본 소멸자가 포함된다.

사용자의 요구 동작을 수행하기 위해 구현하는 경우가 있다.

Circle.h 

 

#ifndef CIRCLE_H
#define CIRCLE_H

class Circle {
public:
	Circle();
	Circle(double);
	~Circle(); // 소멸자 
	double getArea();
	double getRadius();
	void setRadius(double);
	static int getNumberOfObjects();


private:
	double radius;
	static int numberOfObjects;
};
#endif

Circle.cpp

#include "Circle.h"

int Circle::numberOfObjects = 0; //정적멤버 초기화

Circle::Circle() 
{
	radius = 1;
	numberOfObjects++;
}

Circle::Circle(double radius) 
{
	this->radius = radius;
	numberOfObjects++;
}

Circle::~Circle() //소멸자
{  
	numberOfObjects--;
}

double Circle::getArea()
{
	return radius * radius * 3.14159;
}

double Circle::getRadius() 
{
	return radius;
}

void Circle::setRadius(double radius) 
{
	this->radius = (radius >= 0) ? radius : 0;
}

int Circle::getNumberOfObjects() 
{
	return numberOfObjects;
}

main.cpp

#incldue<iostream>
#include"Circle.h"
using namespace std;

int main() 
{
	Circle* pCircle1 = new Circle();
	Circle* pCircle2 = new Circle(5.0);
	Circle* pCircle3 = new Circle(2);

	cout << "원의 개수: " << Circle::getNumberOfObjects() << endl;
	delete pCircle1;
	pCircle1 = NULL;
	cout << "원의 개수: " << Circle::getNumberOfObjects() << endl;

	system("pause");
	return 0;
}

실행 결과

소멸자가 없었으면 삭제후에도 3이 나온다.

 

복사 생성자

동일 클래스의 다른 객체의 데이터를 초기화 된 객체를 생성하는데 사용한다.

Circle circle1 (5); 
Circle circle2 (circle1);
Circle circle3 = circle1;

Circle 클래스의 복사 생성자의 시그니쳐는 아래와 같다.

Circle (const Circle&)

복사생성자를 정의하지 않으면 기본 복사 생성자가 각 클래스에 제공된다.

기본 복사 생성자는 얕은 복사를 수행한다.

 

얕은 복사 vs 깊은 복사

얕은 복사 : 포인터의 주소가 복사된다.

깊은 복사 : 포인터의 내용이 복사된다.

즉, 얕은 복사를 하면 복사후 원본을 변경하면 복사본도 같이 변경된다.

 

얕은복사

Course.h

#ifndef CIRCLE_H
#define CIRCLE_H

class Course
{
public:
	Course(const string& courseName, int capacity);
	~Course();
	void addStudent(const string& name);
	string* getStudents() const;
	int getNumberOfStudents() const;

private:
	string courseName;
	string* students;
	int numberOfStudents;
	int capacity;
};
#endif

Course.cpp

#include "Course.h"

Course::Course(const string& courseName, int capacity)
{
	numberOfStudents = 0;
	this->courseName = courseName;
	this->capacity = capacity;
	students = new string[capacity];
}

Course::~Course() 
{
	//delete[] students; //얕은복사에서 에러
}

void Course::addStudent(const string& name) 
{
	students[numberOfStudents] = name;
	numberOfStudents++;
}

string* Course::getStudents() const 
{
	return students;
}

int Course::getNumberOfStudents() const 
{
	return numberOfStudents;
}

main.cpp

#include <iostream>
#include "Course.h"
using namespace std;

int main() 
{
	Course course1("C++ Programming", 10);
	Course course2(course1);

	course1.addStudent("Peter Pan"); // Add a student to course1
	course2.addStudent("Lisa Ma"); // Add a student to course2

	cout << "students in course1: " << course1.getStudents()[0] << endl;
	cout << "students in course2: " << course2.getStudents()[0] << endl;

	system("pause");
	return 0;
}

실행 결과

 

깊은복사

Course.h

#ifndef CIRCLE_H
#define CIRCLE_H

class Course 
{
public:
	Course(const string& courseName, int capacity);
	~Course();
	Course(const Course&); //복사생성자 

	void addStudent(const string& name);
	string* getStudents() const;
	int getNumberOfStudents() const;

private:
	string courseName;
	string* students;
	int numberOfStudents;
	int capacity;
};
#endif

Course.cpp

#include "Course.h"

Course::Course(const string& courseName, int capacity)
{
	numberOfStudents = 0;
	this->courseName = courseName;
	this->capacity = capacity;
	students = new string[capacity];
} 

Course::~Course() 
{
	delete[] students; //에러안남
}

//복사생성자
Course::Course(const Course& course)
{
	courseName = course.courseName;
	numberOfStudents = course.numberOfStudents;
	capacity = course.capacity;
	students = new string[capacity];

	for (int i = 0; i < numberOfStudents; i++)
		students[i] = course.students[i];
}
void Course::addStudent(const string& name) 
{
	students[numberOfStudents] = name;
	numberOfStudents++;
}

string* Course::getStudents() const 
{
	return students;
}

int Course::getNumberOfStudents() const 
{
	return numberOfStudents;
}

main.cpp

#include <iostream>
#include "Course.h"
using namespace std;

int main() 
{
	Course course1("C++ Programming", 10);
	Course course2(course1);

	course1.addStudent("Peter Pan"); // Add a student to course1
	course2.addStudent("Lisa Ma"); // Add a student to course2

	cout << "students in course1: " << course1.getStudents()[0] << endl;
	cout << "students in course2: " << course2.getStudents()[0] << endl;

	system("pause");
	return 0;
}

실행 결과

728x90

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

15장 상속과 다형성  (0) 2021.12.09
14장 연산자 오버로딩  (0) 2021.12.09
13장 파일 입력과 출력  (0) 2019.05.21
12장 템플릿, 벡터, 스택  (0) 2019.05.13
11장 포인터와 동적 메모리 관리(전)  (0) 2019.05.08
10장 객체 지향 개념  (0) 2019.02.11
9장 객체와 클래스  (0) 2019.01.19
8장 다차원 배열  (0) 2019.01.16

댓글