[C++] 4장. #1 객체 포인터와 객체 배열

2023. 12. 4. 19:51· 프로그래밍/C++
객체 포인터

 

포인터란 주소값을 저장해 주소에 있는 값들을 호출하는 변수이고, 코드를 쉽게 이해하기 위해 앞으로 포인터는 "무언가를 가리키고 있는 변수 '→' "로 생각합시다.

 

다음은 객체 포인터를 이용한 코드입니다. 

Rectangle A;
int a = A.getArea();

Rectangle *p;
p = &A;
a = p ->getArea();

 

Rectangle 타입의 객체에 대한 포인터 변수 p는 " Rectangle *p; " 로 선언합니다. 선언된 포인터는 주소를 지정하지 않은 한 아무 객체도 가리키지 않습니다. (객체 생성 시 자동으로 그 객체를 가리키지 않습니다.)

 

※ 따라서 초기화를 하지 않는다면 객체에 대한 멤버 함수 접근이 불가하기에 오류가 발생합니다.

 

객체 주소 지정은 "& 연산자"를 사용해 " p = &A; " 로 지정하며 포인터 선언 시에 초기화를 할 수도 있습니다. " Rectangle *p = &A; "

 

int a = A.getArea(); 처럼 객체가 멤버 함수에 접근할 때는 ". 연산자 "를 사용하지만, 객체 포인터로 멤버 함수에 접근할 때는 "  -> 연산자 "를 사용합니다. " a = p -> getArea(); " 혹은 " a = (*p). getArea(); " 로 선언할 수 있습니다.

 

객체 배열

 

객체 배열은 원소가 객체인 배열이며 나머지는 일반적인 배열 개념과 동일합니다.

 

다음은 객체 배열을 이용한 코드입니다.

Rectangle rectangle_array[3];

rectangle_array[0].valueIn(10); //valueIn(int n)과 getArea()은 클래스에 선언된 맴버 함수라고 합시다.
rectangle_array[1].valueIn(20);
rectangle_array[2].valueIn(30);

// 출력
for(int i=0; i<3; i++)
	cout << rectangle_array[i].getArea(); << endl;

Rectangle *p;
p = rectangle_array;
for(int i=0; i<3; i++){
	cout << p->getArea() << endl;
    p++;
    }

 

객체 배열 선언은 객체이름을 타입으로 적고 배열을 선언하면 됩니다. ( " Rectangle rectangle_array [3]; " ) 이때 배열은 객체를 원소로 가지므로 위의 코드에서는 총 3개의 객체를 저장할 수 있는 배열이 만들어지는 겁니다. 

 

일반적인 배열과 비슷하게 객체 포인터를 p = rectangle_array로 지정한다면 포인터는 rectangle_array[0]을 가리킵니다.

 

객체 배열 선언시 객체들의 생성자는 어떻게 되나요?

 

 

매개변수를 받는 방식으로 생성자를 지정할 수 있지만, 객체 배열로 선언된 객체들은 매개 변수 없는 기본 생성자를 호출합니다.

 

때문에 클래스에서 아무 생성자가 없다면 객체 배열이 만들어질 때 자동으로 생성자를 만들어 컴파일 오류가 발생하지 않지만, 매개 변수가 있는 생성자만 선언한다면 매개 변수가 없는 생성자가 자동으로 만들어지지 않아 컴파일 오류가 발생할 것입니다.

 

※ 앞으로 객체 배열을 선언할 때 생성자를 필수적으로 확인해야 합니다.

 

맴버 함수의 호출은 객체를 생성 시 ". 연산자"를 사용했던 것처럼 아래와 같이 작성하면 됩니다.

rectangle_array[0].valueIn(10);
rectangle_array[1].valueIn(20);
rectangle_array[2].valueIn(30);

 

다음으로 객체 배열을 생성할 때 생성자를 사용하여 원소 객체를 초기화할 수 있습니다. rectangle(10), rectangle(20)은 생성자 rectangle(int n)을 호출합니다.

Rectangle rectangle_array[3] = { rectangle(10), rectangle(20), rectangle() };

 

마지막으로 함수 종료 시 객체 배열이 소멸할 때 각 원소 객체마다 소멸자가 호출됩니다. 이때 높은 인덱스부터 ~rectangle(); 가 실행됩니다. 

 

  • 객체 포인터를 이용한 객체 배열 사용

 

객체 포인터를 이용해 객체 배열을 호출하려면 p = rectangle_array로 지정 시 " p-> getArea() " 하면 rectangle_array [0] 객체의 getArea() 멤버 함수에 접근할 수 있다는 점을 이용합니다.

 

또한 p [i]는 배열 i 번째 rectangle 객체라는 점을 생각하면 " p [0]. getArea(); "이나 " (*p). getArea(); " 같은 형식으로도  rectangle 객체의 getArea() 함수를 호출할 수 있습니다.

 

  • 다차원 객체 배열

일차원 배열에 차원하나를 더 사용하며 변하는 개념은 없습니다.

Rectangle retangle_array[2][3]; // 2차원 객체 배열 생성

rectangle_array[0][0].valueIn(10);
rectangle_array[1][1].valueIn(20);
rectangle_array[1][2].valueIn(30);
...

 

똑같이 클래스 이름으로 객체 배열을 생성하고, ". 연산자 "를 사용해 멤버 함수를 호출합니다.

Rectangle rectangle_array[2][3] = { {rectangle(10), rectangle(20), rectangle() },
                                  { {rectangle(30), rectangle(40), rectangle()} };

 

위와 같이 초기화도 일반적인 배열을 초기화하는 방식으로 하면 됩니다.

 

동적 메모리 할당 및 반환

 

간단한 코드를 작성할 때는 변수, 객체, 배열을 정적으로 선언해 필요한 메모리를 확보할 수 있지만, 복잡한 코드를 작성할 때는 어느 정도의 메모리가 필요한지 가늠이 안 갈 때가 있습니다.

 

이때 사용하는 것이 "동적 메모리 할당/반환 메커니즘"이며, C언어에서는 주로 malloc()/free()등의 표준 C함수를 이용하지만, C++에서는 새로운 연산자를 사용해 메모리를 동적으로 할당합니다.

 

다음은 메모리를 할당받고 반환하는 코드입니다.

int *point_int = new int; // int 타입의 정수 공간 할당
char *point_char = new char; // char 타입의 문자 공간 할당
Rectangle *point_rectangle = new rectangle(); // Rectangle 클래스 타입의 객체 할당

delete point_int; // 할당된 정수 공간 반환
delete point_char; // 할당된 정수 공간 반환
delete point_rectangle; // 할당된 정수 공간 반환

 

new 연산자는 " 데이터 타입 *포인터변수 = new 데이터타입 " 으로 데이터타입의 크기만큼 힘으로부터 메모리를 할당받고 주소를 리턴합니다. 이렇게 되면 포인터 변수는 할당받은 메모리의 주소를 가지게 됩니다. 이때 데이터 타입은 구조체나 클래스도 포함합니다.

 

" 데이터 타입 *포인터변수 = new 데이터타입(초기값) " 으로 동적 할당 메모리를 초기화할 수 있습니다.

 

※ 만약 힙메모리가 부족하면 NULL값을 리턴하므로, if(! point) return; 같이 메모리 할당이 실패한 경우를 대비해야 합니다.

 

delete 연산자는 " delete 포인터 변수 " 로 포인터변수가 가리키는 메모리를 힙으로 반환합니다. delete를 사용하는 기본전제는 메모리가 동적으로 할당된 포인터 변수를 사용하는 것이기에 포인터 변수가 new로 공간 할당을 받았는지 확인해야 합니다. 또한 한번 반환된 포인터 변수를 중복해서 반환할 수 없습니다.

 

 new와 delete 연산자를 이용해 배열을 할당받고 반환할 수 있습니다. 이때 new 연산자는 배열의 크기만 한 배열을 할당받아 주소를 리턴합니다. 

데이터 타입 *포인터변수 = new 데이터타입[배열의 크기]; // 배열의 동적 할당
delete [] 포인터변수; // 배열 메모리 반환

 

아래는 배열을 할당받고 반환하는 기초 코드입니다.

int *p= new int [10]; // 크기가 10인 정수형 배열의 동적 할당
if(!p)
    return; // 메모리 할당 실패 대비
    
for(int i=0; i<10; i++)
    p[i]=i; // *(p+i) = i; 와 동일

delete [] p; // 배열 메모리 반환

 

※ new로 배열을 동적 할당받을 때 직접 초깃값을 지정할 수 없습니다. 즉, new int [10](1)은 안되지만 new int [] {1,2,3,4,5...}; 같은 형식은 가능합니다.

'프로그래밍 > C++' 카테고리의 다른 글

[C++] 5장. #1 함수 호출 시 객체 전달  (2) 2023.12.08
[C++] 4장. #2 this 포인터와 string 클래스  (0) 2023.12.08
[C++] 3장. #2 접근 지정자와 인라인 함수  (1) 2023.12.03
[C++] 3장. #1 클래스와 객체  (0) 2023.12.02
[C++] 2장. #2 입력 받기  (0) 2023.11.30
'프로그래밍/C++' 카테고리의 다른 글
  • [C++] 5장. #1 함수 호출 시 객체 전달
  • [C++] 4장. #2 this 포인터와 string 클래스
  • [C++] 3장. #2 접근 지정자와 인라인 함수
  • [C++] 3장. #1 클래스와 객체
w_w
w_w
데이터 사이언스가 목표인 학생입니다. / 공부한 내용을 간단히 정리하는 블로그입니다. / 비공개 게시글은 저작권 보호를 위해 개인 소장 용도로만 사용합니다.
공부용데이터 사이언스가 목표인 학생입니다. / 공부한 내용을 간단히 정리하는 블로그입니다. / 비공개 게시글은 저작권 보호를 위해 개인 소장 용도로만 사용합니다.
w_w
공부용
w_w
전체
오늘
어제
  • 전체 글 (78)
    • 대표글 (4)
    • 프로그래밍 (71)
      • C++ (8)
      • Python (1)
      • 알고리즘 (1)
      • 코딩 테스트 연습 (61)
      • 게임 (0)
    • 데이터베이스 (0)
      • 데이터 분석 및 시각화 (0)
      • 머신 러닝 (0)
    • 공학 (2)
      • 수학 기본 개념 (2)
    • 정보 (1)
      • AICE (1)
      • Excel (0)
      • Access (0)
      • kaggle (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 데이터 연산
  • Matplotlib
  • 바이너리 파일
  • 프로그래밍 언어
  • 머신러닝
  • c++
  • 그래프 꾸미기
  • 바이너리I/O
  • 텍스트I/O
  • 알고리즘
  • 연산자
  • 객체
  • 그래프 저장하기
  • 데이터 분석 패키지
  • K-평균 군집화
  • Excel
  • pandas
  • 연산자 중복
  • IT
  • 연결 리스트
  • 자료구조
  • C언어 링킹
  • K-최근접 이웃
  • 머신 러닝
  • 백준
  • 데이터 분석
  • 클래스
  • 엑셀 파일 통합
  • python
  • 데이터 시각화

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
w_w
[C++] 4장. #1 객체 포인터와 객체 배열
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.