- 데이터를 저장할 때 프로그램이 알아야 하는 것
- 어디에 저장되는가?
- 어떤값이 저장되는가?
- 어떤 종류의 정보인가?
->변수 / 포인터를 이용
- 포인터
- 값의 주소를 저장하는 변수
- 메모리 관리에 필수적이다
- 포인터의 이름이 주소를 나타낸다
- &
- 참조연산자
- 주소연산자
- 변수 앞에 붙이면 그 변수의 주소
- *
- 역참조 연산자
- 포인터 이름 앞에 붙이면 그 주소에 저장되어 있는 값
- 역참조 연산자
& 연산자로 주소를 알아낸다
int donuts = 6;
double cups = 4.5;
cout<< "donuts의 값 = " << donuts;
cout<< ", donuts의 주소 = " << &donuts <<endl;
cout<< "cups의 값 = " << cups;
cout<< ", cups의 주소 = " << &cups <<endl;
-> 16진수 표기를 사용한 주소값 출력
-> 4바이트 차이 [int 이므로]
-> 8바이트 차이 [double 이므로]
- 포인터와 C++
- 절차지향 [C]
- 컴파일 시간에 결정
- 객체지향 (OOP) [C++]
- 실행시간에 결정
- 상황에 대처할 수 있는 유연성
- 실행시간에 결정
- 절차지향 [C]
포인터 변수
int updates = 6;
int * p_updates;
p_updates = &updates;
-> * : 포인터 이름앞 -> 그 주소의 값
-> & : 변수 앞 -> 그 변수의 주소
-> *p_updates는 int형 변수 updates와 동등하게 취급하고 사용할 수 있다
=
int jumbo = 23;
int *pe = &jumbo;
jumbo *pe |
&jumbo pe |
값 23 | 주소 0x2ac8 |
=> 값과 주소를 두 가지의 형태로 표현할 수 있다. => 어떤 형태를 쓰든 동등하게 취급한다. |
- 포인터 선언과 초기화
- 포인터를 선언하는 과정
- 포인터가 지시하는 값의 데이터형을 파악 해야한다. [주소값으로 데이터형 구분이 불가하므로]
- 포인터를 선언하는 과정
int* p_updates;
-> p_updates : 포인터
-> * p_updates : int형 변수
-> int* p_updates : int형 포인터
-> int* : 하나의 데이터형
- 포인터 변수 선언시 주의
- int* p1, p2;
- int형 포인터 p1
- int형 변수 p2 [int형 포인터가 아니라 변수를 선언한다.]
- int* p1, p2;
포인터와 수
int* pt
pt = 0XB8000000;
pt = (int *) 0XBB8000000;
-> pt에 바로 주소를 넣는 경우 데이터형 불일치
-> (int *)라는 데이터형 변환자를 넣어줘야 데이터형 일치
-> 데이터형 변환자 : 뒤의 값이 주소값임을 명시
// init_ptr.cpp -- 포인터를 초기화한다
#include <iostream>
int main()
{
using namespace std;
int higgens = 5;
int * pt = &higgens;
cout << "higgens의 값 = " << higgens
<< ", higgens의 주소 = " << &higgens << endl;
cout << "*pt의 값 = " << *pt
<< ", pt의 값 = " << pt << endl;
return 0;
}
실행결과:
-> pt가 higgens의 주소로 초기화
포인터를 사용할 때는 *를 사용하기 전에 반드시 &로 초기화를 해야 한다.
- 포인터들을 변수의 주소로 초기화
- 프로그램 실행동안에 unnamed 메모리를 대입
- C : malloc() / free()
- C++ : new / delete
- new 연산자
- 이름이 없는 데이터의 주소를 반환한다.
- 필요한 데이터형을 전달
- 적당한 메모리를 찾아 블록 대입
- 주소를 반환, 주소 포인터에 대입
- 이름이 없는 데이터의 주소를 반환한다.
차이 비교
int* pn = new int;
-> pn이 데이터 객체[메모리 블록]를 지시
-> pn이 값에 접근할 수 있는 유일 경로
int higgens;
int* pt = &higgens;
-> pt, higgens 둘 다 int형 값에 접근 가능
기본형
typename* pointer_name = new typename;
-> 메모리 종류 지정
-> 포인터 선언
- delete를 사용한 메모리 해제
- delete를 이용해 new로 할당한 메모리 해제 [동일한 주소]
- 해제한 이후에 다시 해제 불가
- 보통의 변수로 선언한 메모리는 delete로 해제불가
// arraynew.cpp -- 배열을 위해 new 연산자 사용
#include <iostream>
int main()
{
using namespace std;
double * p3 = new double [3]; // double형 데이터 3개를 저장할 수
// 있는 공간을 대입한다
p3[0] = 0.2; // p3을 배열 이름처럼 취급한다
p3[1] = 0.5;
p3[2] = 0.8;
cout << "p3[1]은 " << p3[1] << "입니다.\n";
p3 = p3 + 1; // 포인터를 증가시킨다
cout << "이제는 p3[0]이 " << p3[0] << "이고, ";
cout << "p3[1]이 " << p3[1] << "입니다.\n";
p3 = p3 - 1; // 다시 시작 위치를 지시한다
delete [] p3; // 배열 메모리를 해제한다
return 0;
}
-> p3 = p3+1;
-> p3가 포인터면 가능 [값 변경 가능]
-> p3가 배열이면 불가능 [값 변경 불가능]
- new를 사용한 동적 배열의 생성
- 선언을 이용해 배열을 생성
- 컴파일 시간에 메모리에 대입
- 정적 바인딩
- 사용이 되든 안되든 정해둔 배열의 크기로 항상 메모리를 차지
- 정적 바인딩
- 컴파일 시간에 메모리에 대입
- new를 사용해 배열을 생성
- 실행 시간에 생성여부 결정
- 동적 바인딩
- 실행되든 동안에 배열의 크기와 생성여부 결정
- 동적 바인딩
- 실행 시간에 생성여부 결정
- 선언을 이용해 배열을 생성
배열의 생성
int* psome = new int[10];
-> 배열 원소의 데이터형 : int
-> 배열 원소의 개수 : [10]
=> new 연산자는 그 블록의 첫번째 원소의 주소를 반환한다.
배열의 해제
delete [] psome;
동적 배열을 위한 메모리 대입하고, 그 배열의 시작 주소를 포인터에 대입
type_name* pointer_name = new type_name [num_elements];
동적 배열의 사용
int* psome = new int [10];
-> psome[0], psome[1] 등으로 접근
'Programming > C++ 2' 카테고리의 다른 글
[C++ 실습] 4장-02. 문자열 (0) | 2021.04.04 |
---|---|
[C++ 실습] 4장-01. 배열 (0) | 2021.04.04 |
[C++] 4장. 복합 데이터형 - (5) 공용체와 (6) 열거체 (0) | 2021.03.27 |
[C++] 4장. 복합 데이터형 - (4) 구조체 (0) | 2021.03.27 |
[C++] 4장. 복합 데이터형 - (3) String 클래스 (0) | 2021.03.27 |