• 객체 포인터

Circle 객체에 대한 포인터 변수를 선언하고 활용하는 사례를 보자.

1
2
3
4
5
6
Circle donut;
double d = donut.getArea();
 
Circle *p;
= &donut;
= p->getArea();
cs


먼저 Circle타입의 객체에 대한 포인터 변수는 다음과 같이 선언한다.

1
Circle *p;
cs


포인터 변수 p에 객체 donut의 주소를 저장한다.

1
= &donut;
cs


이때, 선언과 동시에 초기화를 할 수 도 있다.

초기화가 되어있지 않다면 멤버로 접근할 수 없다.

1
Circle *= &donut;
cs


객체 이름으로 접근할때는 점(.)을 이용하지만

1
= donut.getArea();
cs


객체 포인터로 접근할 때는 -> 연산자를 이용한다.

1
2
= p->getArea();
//d = (*p).getArea(); 와 
cs



  • 객체 배열

객체 배열은 원소가 객체라는점을 빼고, int, double등 기본타입의 배열을 선언하고 활용하는 방법과 동일하다.

다음 코드는 Circle 객체의 배열 circleArray를 선언하는 코드이다.

1
Circle circleArray[3];
cs


객체 배열 선언문은 기본 생성자를 호출한다.

아무런 생성자도 선언되어있지 않으면 기본 생성자를 호출한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
 
using namespace std;
 
class Circle{
    int radius;
public:
    double getArea(){
        return 3.14*radius*radius;
    }
};
 
int main(){
    Circle circleArray[3];    //기본 생성자 호출
}
cs


다음과 같이 기본생성자가 아닌 매개변수를 가진 생성자만 선언되어 있는 경우는

객체 배열로 선언을 하면 기본생성자가 없기때문에 컴파일에러가 발생한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
 
using namespace std;
 
class Circle{
    int radius;
public:
    Circle(int r)    { radius = r; }    //매개변수가 있는 
    double getArea(){
        return 3.14*radius*radius;
    }
};
 
int main(){
    Circle circleArray[3];    //컴파일에러
}
cs


Circle 객체의 setRadius() 멤버함수를 호출하는 코드인데, 원소와 객체 사이에 점(.) 연산자를 사용한다.

1
2
3
circleArray[0].setRadius(10);
circleArray[1].setRadius(20);
circleArray[2].setRadius(30);

cs


또는 다음과 같은 방법으로 초기화도 가능하다.

1
Circle circleArray[3= { Circle(10), Circle(20), Circle() };
cs


소멸자도 마찬가지로

각 원소의 객체마다 소멸자가 호출되며, 높은 인덱스의 원소 객체가 먼저 소멸된다.

circleArray[2] 소멸자 실행 -> circleArray[1] 소멸자 실행 -> circleArray[0]



다차원 객체배열의 경우도 동일하다.

2행 3열의 2차원 객체배열을 생성하기 위해서는 아래의 코드를 작성하면 된다.

1
Circle circles[2][3];
cs


초기화까지 한번에 하고싶다면, 다음과 같이 하면 된다.

아무런 매개변수를 전달하지 않은 생성자는 당연히 기본 생성자가 생성되어 기본으로 설정해 두었던 1로 세팅이 된다.

1
2
Circle circles[2][3= { {Circle(1), Circle(2), Circle(3)}, 
                         {Circle(4), Circle(5), Circle()} };
cs




  • 동적 메모리 할당 및 반환

C언어 : malloc(), free() 등의 표준 함수 사용

C++ : new, delete 연산자를 사용


new 연산자는 힙(heap) 에서 메모리를 할당받고, delete 연산자는 다시 메모리를 힙(heap)으로 반환한다.


new와 delete 연산자의 기본 형식은 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
/*
    데이터타입 *포인터변수 = new 데이터타입;
    delete 포인터변수;
*/
int *pInt = new int;    // int 타입의 정수 공간 할당
char *pChar = new char;    // char 타입의 문자 공간 할당
Circle *pCircle = new Circle    //Circle 클래스 타입의 객체 할당
 
delete pInt;
delete pChar;
delete pCircle;
cs



이때, 힙(heap) 메모리가 부족하다면 new는 NULL을 return 하므로, new의 return 값이 NULL인지 아닌지 검사하는것이 좋다.

1
2
3
4
5
6
7
int *= new int;    // int 타입의 정수 공간 p 할당
if(!p){    // p==NULL 과 동일
    return;
}
*= 5;
int n = *p;
delete p;    //포인터 p는 살아있지만, 할당된 영역이 없으므로 접근하면 안된다.
cs


동적 메모리 할당과 동시에 초기화도 가능한데 다음과 같이 하면된다.

1
2
3
4
5
/*
    데이터타입 *포인터변수 = new 데이터타입(초깃값);
*/
int *pInt = new int(20);
char *pChar = new char('a');
cs



delete사용시 주의할 점이 있는데,

첫번째로 동적으로 할당받지 않은 메모리를 반환할 때 이다.

1
2
3
int n;
int *= &n;
delete p;    //실행 오류. p가 가리키는 n은 정적으로 할당받은 메모리이다.
cs


두번째로 이미 반환한 메모리를 한번 더 반환할 때 이다.

중복으로 메모리를 반환할 수는 없다.

1
2
3
int *= new int;
delete p;    //정상 반환
delete p;    //실행 오류. 이미 반환됨.
cs



배열도 동적할당을 할 수 있는데, 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
/*
    데이터타입 *포인터변수 = new 데이터타입 [배열의크기];
    delete [] 포인터변수;
*/
int *= new int[5];
if(!p)
    return;
 
for(int i=0; i<5++i)
    p[i] = i;    //동적으로 할당 받은 배열은 []를 이용하여 보통 배열과 동일한 방법으로 사용한다.
 
delete [] p;
cs



하지만 new로 배열을 동적 할당받을때 생성자를 통해 초기화는 불가능하다.

그래서 다음과 같이 초기화를 한다.

1
int *pArray = new int[] {1,2,3,4};
cs


Posted by Jyoel :