포인터도 변수다 그러므로 메모리주소를 가지고 있다.
즉, 변수이기에 포인터에대한 포인터를 생성할 수 있다.
2중포인터 기본개념
int **ptr은 int *(*ptr)로 이해할 수 있다.
즉, *ptr이 가지고 있는 주소값을 또 포인터로 보게하는 것이다.
2중포인터 예
ptr은 int val의 주소값을 가진다.
int val = 5;
int *ptr = &val;
ptrptr은 ptr(val주소값을 가지고있는 포인터)의 주소값을 가진다.
int **ptrptr = &ptr;
de-reference도 가능하다.
cout << **ptrptr << endl;
동적 메모리 할당을 이용해 다차원배열 생성
동적 메모리 할당을 이용해 다차원배열생성을 알아보기전에
배열과 포인터는 같다는걸 잊지말자!
2차원 배열을 동적할당으로 생성한다고 보면 우선 포인터 3개를 생성한다.
int *(*rows) = new int *[3];
//포인터 찍어본결과 임의의 주소값이 들어있다.
그다음 for문으로 포인터에 접근해 포인터에 배열을 선언해준다.
for (int i = 0; i < 3; i++) {
rows[i] = new int[5]{};
}
아래 배열과 비슷하게 생성된다.
int rows[3][5] = {};
비슷하다고한 이유는?
메모리주소 형식이 다르다.
위에 선언된 정적2차원배열은 메모리주소가 이어진다.
하지만 동적 메모리 할당을 이용하면 메모리 주소가 이어지지 않는다.
위에 말했듯이 포인터도 메모리 주소가 있다.
동적할당 3개를 받은 포인터에
rows[i] = new int[5]{};
의 새로운 포인터주소를 정의해주면 주소가 이어지진않지만 2차원배열이 생성되는걸 알 수 있다.
즉, 동적할당된 3개의 포인터에 새로운 배열의 주소를 정의해준다.
동적할당은 사용한후 메모리를 반납하는걸 잊지말자!
for (int r = 0; r < row; r++) {
delete[] rows[r];
}
delete[] rows;
#include <iostream>
using namespace std;
int main()
{
int *ptr = nullptr;
int **ptrptr = nullptr;
int value = 5;
//value의 주소 ptr포인터에 저장
ptr = &value;
//ptr포인터의 주소 ptrptr포인터에 저장
ptrptr = &ptr;
cout << "==============================================" << endl;
cout << "다중 포인터 기본예" << endl;
cout << "value의 주소값 : " << &value << endl;
cout << endl;
cout << "ptr포인터의 자신의 주소값 : " << &ptr << endl;
cout << "ptr포인터에 저장된 주소값 : " << ptr << endl;
cout << "ptr포인터 de-reference : " << *ptr << endl;
cout << endl;
cout << "ptrptr포인터의 자신의 주소값 : " << &ptrptr << endl;
cout << "ptrptr포인터에 저장된 주소값 : " << ptrptr << endl;
cout << "ptrptr포인터 de-reference(ptr이 가지고있는 주소) : " << *ptrptr << endl;
cout << "ptrptr포인터의 double de-reference : " << **ptrptr << endl;
cout << endl;
//배열과 포인터는 같다.
int a[3] = { 1,2,3 };
int *aa = a;
cout << "==============================================" << endl;
cout << "배열과 포인터 비교" << endl;
cout << "==============================================" << endl;
cout << "a[3]" << endl;
for (int i = 0; i < 3; i++) {
cout << "\t배열안의 값 a : " << a[i] << endl;
cout << "\t배열의 주소 &a : " << &a[i] << endl;
//cout << *ptrTest[i] << endl;
}
cout << "==============================================" << endl;
cout << "*aa" << endl;
for (int i = 0; i < 3; i++) {
cout << "\t배열안의 값 aa : " << aa[i] << endl;
cout << "\t배열의 주소 &aa : " << &aa[i] << endl;
//cout << *ptrTest[i] << endl;
}
cout << "==============================================" << endl;
cout << "1차배열 동적할당" << endl;
cout << "*ptrTest = new int [3]" << endl;
int *ptrTest = new int [3];
for (int i = 0; i < 3; i++) {
cout << "\t배열안의 주소 &ptrTest[i] : " << &ptrTest[i] << endl;
cout << "\t배열안의 값 ptrTest[i] : " << ptrTest[i] << endl;
ptrTest[i] = 3;
cout << "\t배열안의 값 ptrTest[i] : " << ptrTest[i] << endl;
//cout << *ptrTest[i] << endl;
}
cout << "==============================================" << endl;
cout << "2차배열 동적할당" << endl;
cout << "int *(*ptrTest2) = new int *[3]" << endl;
int *(*ptrTest2) = new int *[3];
cout << "ptrTest2 : " << ptrTest2 << endl;
for (int i = 0; i < 3; i++) {
cout << "\t배열안의 주소 &ptrTest2[i] : " << &ptrTest2[i] << endl;
cout << "\t배열 동작할당 전 ptrTest2[i]: " << ptrTest2[i] << endl;
//에러가난다
//cout << "\t배열 동작할당 후 *ptrTest2[i]: " << *ptrTest2[i] << endl;
//cout << *ptrTest2[i] << endl;
ptrTest2[i] = new int[5]{};
cout << "\t배열 동작할당 후 ptrTest2[i]: " << ptrTest2[i] << endl;
cout << "\t배열 동작할당 후 *ptrTest2[i]: " << *ptrTest2[i] << endl;
}
cout << "==============================================" << endl;
const int row = 3;
const int col = 5;
int (*arr2)[col] = new int [row][col];
for (int i = 0; i < row; i++) {
cout << "상수로 동적할당" << endl;
cout << &arr2[i] << endl;
for (int s = 0; s < col; s++) {
cout << &arr2[i][s] << endl;
}
}
cout << "==============================================" << endl;
int **arr3 = new int *[row];
for (int i = 0; i < row; i++) {
cout << "다중포인터 주소" << endl;
cout << &arr3[i] << endl;
}
cout << "==============================================" << endl;
for (int i = 0; i < row; i++) {
cout << "다중포인터 생성" << endl;
arr3[i] = new int[5]{};
for (int s = 0; s < col; s++) {
cout << &arr3[i][s] << endl;
}
}
cout << "==============================================" << endl;
int arr[row][col] =
{
{1,2,3,4,5},
{},
{}
};
int *(*rows) = new int *[row];
cout << "rows에 저장된 주소값 : " << rows << endl;
cout << " *de-reference : " << *rows << endl;
cout << "&포인터의 주소값 : " << &rows << endl;
cout << endl;
//초기화
for (int r = 0; r < row; r++) {
rows[r] = new int[col];
cout << "초기화" << endl;
cout << "&rows[" << r << "] : " << &rows[r] << endl;
cout << "rows[" << r << "] : " << rows[r] << endl;
int *a = &rows[r][0];
cout << "a : " << a << endl;
cout << "rows[" << r << "][0] : " << rows[r][0] << endl;
}
cout << endl;
cout << "*de-reference : " << *rows << endl;
cout << "**de-reference : " << **rows << endl;
cout << "pointer : " << rows << endl;
cout << endl;
for (int r = 0; r < row; r++) {
cout << "&rows["<< r <<"] : " << &rows[r] << endl;
cout << endl;
for (int i = 0; i < col; i++) {
rows[r][i] = arr[r][i];
cout << "&rows[" << r << "]["<< i <<"]" << &rows[r][i] << endl;
cout << "rows[" << r << "][" << i << "]" << rows[r][i] << endl;
}
cout << "===================================" << endl;
}
//메모리 제거
for (int r = 0; r < row; r++) {
delete[] rows[r];
}
delete[] rows;
//다중배열 사용하지 않기
int *arrx2 = new int[row*col];
for (int r = 0; r < row; r++) {
for (int i = 0; i < col; i++) {
cout << " i + col * r : " << i + col * r << endl;
arrx2[i + col * r] = arr[r][i];
}
}
for (int r = 0; r < row; r++) {
for (int i = 0; i < col; i++) {
cout << arrx2[i + col * r] << " ";
}
cout << endl;
}
delete[] arrx2;
return 0;
}
'개발 소발 > 개발 C++(기초)' 카테고리의 다른 글
c++ 매개변수(parameter),인자(Argument),값에 의한 인수 전달 (CallbyValue) (0) | 2019.07.30 |
---|---|
c++ std::array,std::vector (0) | 2019.07.30 |
c++ void pointer,generic pointer (0) | 2019.07.29 |
c++ for-each문 반복문 (0) | 2019.07.29 |
c++ 포인터,참조의 구조체,클래스 멤버선택 (0) | 2019.07.29 |