Chapter 4. 객체 포인터¶
'명품 C++Programming - 황기태' 4장 학습 내용
1절. 객체
2절. 동적 할당
3절. 배열의 동적 할당
4절. this
5절. string
1절. 객체¶
객체 포인터¶
- 객체에 대한 포인터
- C언어의 포인터와 동일
- 객체의 주소값을 가지는 변수
- 포인터로 멤버를 접근할 때
- 객체 포인터 -> 멤버
Circle donut;
double area = donut.getArea();
Circle *p;
// (1) 객체에 대한 포인터 선언
p = &donut;
// (2) 포인터에 객체 주소 저장
d = p->getArea();
// (3) 멤버 함수 호출
- 예제 1. 객체 포인터 선언 및 활용 예제
SourceCodeChecking
객체 배열 생성 및 소멸¶
- 객체 배열 선언 가능
- 기본 타입 배열 선언과 형식 동일
- int n[3]; // 정수형 배열 선언
- Circle c[3]; // Circle 클래스 타입 배열 선언
- 객체 배열 선언
- (1) 객체 배열을 위한 공간 할당
- (2) 배열의 각 원소 객체마다 생성자 실행
- c[0]의 생성자, c[1]의 생성자, c[2]의 생성자 실행
- 매개 변수 없는 생성자 호출
- 매개 변수 있는 생성자를 호출할 수 없음
- Circle circleArray[3] (5); // 오류 발생
-
배열 소멸
-
배열의 각 객체마다 소멸자 호출
-
생성의 반대 순으로 소멸
- c[2]의 소멸자, c[1]의 소멸자. c[0]의 소멸자 실행
-
예제 2. Circle 클래스 배열 선언 예제
SourceCodeChecking -
예제 2의 설명
객체 배열 생성 시 기본 생성자 호출¶
객체 배열 초기화¶
- 객체 배열 초기화 방법
- 배열의 각 원소 객체 당 생성사 지정하는 방법
- circleArray[0] 객체가 생성될 때, 생성자 Circle(10) 호출
- circleArray[1] 객체가 생성될 때, 생성자 Circle(20) 호출
-
circleArray[2] 객체가 생성될 때, 생성자 Circle() 호출
-
예제 3. 객체 배열 초기화 예제
SourceCodeChecking
2차원 배열¶
-
2차원 배열 선언
-
2차원 배열 선언과 초기화
-
2차원 배열을 초기화하는 다른 방식
-
예제 4. Circle 클래스 2차원 배열 선언 예제
SourceCodeChecking
2절. 동적 할당¶
동적 메모리 할당 및 변환¶
- 정적 할당
- 변수 선언을 통해 필요한 메모리만 할당
- 많은 양의 메모리는 배열 선언을 통해 할당
- 동적 할당
- 필요한 양이 예측되지 않는 경우
- 프로그램 작성 시 할당받을 수 없음
- 실행 중 운영체제로부터 할당
- 힙(heap)으로부터 할당
- 힙은 운영체제가 소유하고 관리하는 메모리
- 모든 프로세스가 공유할 수 있는 메모리
- C 언어의 동적 메모리 할당
- malloc() / free() 라이브러리 함수 사용
- C++의 동적 메모리 할당 및 반환
- new 연산자
- 기본 타입 메모리 할당, 배열 할당, 객체 할당, 객체 배열 할당
- 객체의 동적 생성
- 힙 메모리로부터 객체를 위한 메모리 할당 요청
- 객체 할당 시 생성자 호출
- delete 연산자
- new로 할당받은 메모리 반환
- 객체의 동적 소멸
- 소멸자 호출 뒤 객체를 힙에 반환
new와 delete 연산자¶
- C++의 기본 연산자
- new 연산자의 사용 형식
- delete 연산자의 사용 형식
- new와 delete 연산자의 사용 예시
int *pInt = new int;
// int 타입의 메모리 동적 할당
char *pChar = new char;
// char 타입의 메모리 동적 할당
Circle *pCircle = new Circle;
// Circle 타입의 메모리 동적 할당
delete pInt;
// 할당 받은 정수 공간 반환
delete pInt;
// 할당 받은 문자 공간 반환
delete pInt;
// 할당 받은 객체 공간 반환
기본 탕비의 메모리 동적 할당 및 반환¶
- 예제 5. 정수형 공간의 동적 할당 및 반환 예제
SourceCodeChecking
delete 연산자 주의 사항¶
- 적절치 못한 포인터로 delete 하면 실행시간 오류 발생
- 동적으로 할당받지 않는 메모리 반환 (Error)
int n;
int *p = &n;
delete p;
// 실행 시간 오류 발생
// why ? >> 포인터 p가 가리키는 메모리는 동적으로 할당 받은 것이 아님
// 복사 생성자를 사용한 것(5장 참조)
- 동일한 메모리 두 번 반환 (Error)
int *p = new int;
delete p; // 정상적인 메모리 반환
delete p; // 실행 시간 오류 발생
// why ? >> 이미 반환한 메모리는 중복 반환 불가능
3절. 배열의 동적 할당¶
배열의 동적 할당 및 반환¶
- new와 delete 연산자의 사용 형식
-
그림으로 이해하기
-
예제 6. 정수형 배열의 동적 할당 및 반환 예제
SourceCodeChecking
동적 할당 메모리 초기화 유의 사항¶
- 동적 할당 메모리 초기화
- 동적 할당 시 초기화
int *pInt = new int(20);
// 20으로 초기화된 int 타입 할당
char *pChar = new char('a');
// 'a'로 초기화된 char 타입 할당
- 배열은 동적 할당 시 초기화 불가능
- delete시 [] 생략
- 컴파일 오류는 아니지만 비정상적인 반환
int *p = new int[10];
delete p;
// 비정상적인 반환
// delete [] p; 가 올바른 코드
int *q = new int;
delete [] q;
// 비정상적인 반환
// delete q; 가 올바른 코드
객체의 동적 생성 및 반환¶
ClassName *pointervalue = new ClassName;
ClassName *pointervalue = new ClassName(ConstructorArgumentList);
delete pointervalue;
-
그림으로 이해하기
-
예제 7. Circle 객체 동적 생성 및 반환 예제
SourceCodeChecking -
예제 8. 예제 7 응용 예제
SourceCodeChecking
객체 배열의 동적 생성 및 반환¶
ClassName *pointervalue = new ClassName[ArrayLength];
delete [] pointervalue;
// 포인터 변수가 가리키는 객체 배열 반환
- 그림으로 이해하기
객체 배열의 사용 및 배열의 반환과 소멸자¶
- 동적으로 생성된 배열도 보통 배열처럼 사용
Circle *pArray = new Circle[3];
// 3개의 Circle 객체 배열 동적 생성
pArray[0].setRadius(10);
pArray[1].setRadius(20);
pArray[2].setRadius(30);
// 각각 배열 객체의 setRadius() 멤버 함수를 통해 초기화
for(int i = 0; i < 3; i++)
cout << pArray[i].getArea() << endl;
// 배열의 i 번째 객체 getArea() 멤버 함수를 차례로 호출
- 포인터로 배열 접근
pArray->setRadius(10);
// pArray는 pArray 배열의 첫 번째 주소값으로, pArray[0]과 같음
(pArray + 1)->setRadius(20);
(pArray + 2)->setRadius(30);
// 각각 배열 객체의 setRadius() 멤버 함수를 통해 초기화
for(int i = 0; i < 3; i++)
cout << (pArray + i)->getArea() << endl;
// 배열의 i 번째 객체 getArea() 멤버 함수를 차례로 호출
- 배열 소멸
delete [] pArray;
// 객체의 소멸자 실행
// 각 원소 객체의 소멸자를 별도로 실행하며 생성의 반대 순서로 소멸됨
// 출력 예시
// pArray[2] 객체의 소멸자 실행 (1)
// pArray[1] 객체의 소멸자 실행 (2)
// pArray[0] 객체의 소멸자 실행 (3)
-
예제 9. Circle 배열의 동적 생성 및 반환 예제
SourceCodeChecking -
예제 10. 예제 9 응용 예제
SourceCodeChecking
메모리 할당과 메모리 누수¶
4절. this¶
this 포인터¶
- this
- 포인터의 한 종류
- 객체 자신 포인터
- 클래스의 멤버 함수 내에서만 사용
- 개발자가 선언하는 변수가 아님
- 컴파일러가 선언하는 변수
- 멤버 함수의 컴파일러에 의해 묵시적으로 삽입 선언되는 매개 변수
class Circle{
int radius;
public:
Circle() { this->radius = 1; }
Circle(int radius) { this->radius = radius; }
void setRadius(int radius) { this->radius = radius; }
...
};
this와 객체¶
this가 필요한 경우¶
-
매개 변수의 이름과 멤버 변수의 이름이 같은 경우
-
멤버 함수가 객체 자신의 주소를 리턴할 때
- 연산자 중복 시에 필요
this의 제약 사항¶
- 멤버 함수가 아닌 함수에서 this 사용 불가
- 객체와의 관련성이 없기 때문
- static 멤버 함수에서 this 사용 불가
- 객체가 생기기 전에 static 함수 호출이 있을 수 있기 때문
this 포인터의 실체¶
- 컴파일러에서 처리
5절. string¶
string 클래스를 이용한 문자열¶
- C++ 문자열
- C-스트링
- C++ string 클래스의 객체
- string 클래스
- C++ 표준 라이브러리
헤더 파일에 선언
- 가변 크기의 문자열
string str = "I love ";
// str은 'I', ' ', 'l', 'o', 'v', 'e', ' '의 7개 문자로 구성
// 공백도 포함하는 모습 확인 가능
str.append("C++.");
// str은 "I love C++."의 문자열이 됨
// 11개의 문자
...
- 다양한 문자열 연산을 실행하는 연산자와 멤버 함수 포함
- 문자열 복사, 문자열 비교, 문자열 길이 등
- 문자열, 스트링, 문자열 객체, string 객체 등으로 혼용
string 객체 생성 및 입출력¶
- 문자열 생성
string str;
// 빈 문자열을 가진 스트링 객체
string address("서울특별시 성북구 삼선동 389");
// 문자열 리터럴로 초기화
string copyAddress(address);
// 위의 스트링 객체 address를 복사한 copyAddress 생성
// C-스트링(char[] 배열)으로부터 스트링 객체 생성
char text[] = {'L', 'O', 'V', 'E', ' ', 'C', '+', '+', '\0'};
string title(text);
// "LOVE C++"의 문자열을 가진 title 생성
- 문자열 출력 : cout과 << 연산자 사용
- 문자열 입력 : cin과 >> 연산자 사용
- 문자열 숫자 변환 : stoi() 함수 이용 (2011 C++ 표준부터)
string 객체의 동적 생성¶
- new / delete를 이용하여 문자열을 동적 생성 및 반환 가능
string *p = new string("C++");
// 스트링 객체 동적 생성
cout << *p << endl;
// "C++" 출력
p->append(" Great!");
// p가 가리키는 스트링 : C++ Great!
cout << *p << endl;
// "C++ Great!" 출력
delete p;
// 스트링 객체 반환
-
예제 11. string Class 문자열 생성 및 출력 예제
SourceCodeChecking -
예제 12. string 배열 선언 예제
SourceCodeChecking