포인터
모든 변수는 메모리의 특정 주소에 저장된다. 주소는 다음과 같이 알 수 있다.
#include <iostream>
int main()
{
int x;
std::cin >> x;
std::cout << &x;
}
앞에 &를 붙이면 알 수 있다.
다만 이렇게 하려면, 반드시 값변수를 선언해야 한다. 먼저 값 변수를 선언하지 않고, 메모리 주소로 선언하는 변수가 바로 포인터다.
포인터는 다음과 같이 선언 가능하다.
#include <iostream>
int main()
{
int x = 3;
int* y = &x;
int *z = y;
std::cout << y << std::endl; // 실제 y의 주소
std::cout << *y << std::endl; // y의 값
std::cout << z << std::endl;
std::cout << *z << std::endl;
}
*를 띄어쓰기 하고 붙이거나, 그냥 바로 붙여도 상관없다.
실제 해당 메모리 주소가 표현하는 값을 알고 싶으면 변수명 앞에 *를 붙이면 된다.
포인터는 배열로 선언할 수도 있다.
이때 배열 내부 요소들은 해당 값들의 주소를 가르키게 되며, 배열 포인터 자체는 첫번째 요소를 가르킨다.
using namespace std;
int main()
{
int arr[3] = { 10, 20, 30 };
int* x = arr;
cout << *x << endl; // 10
cout << *(x + 1) << endl; // 20
cout << *(x + 2) << endl; // 30
}
이때 다음과 같이 출력해보자.
using namespace std;
int main()
{
int arr[3] = { 10, 20, 30 };
int* x = arr;
x = x + 1;
cout << *x << endl; // 20
cout << *(x + 1) << endl; // 30
cout << *(x + 2) << endl; // 의미없는 값
}
x+1의 의미는 배열을 메모리 주소를 한칸 뒤로 옮긴다는 것이다. 따라서 x의 첫번째 요소가 20, 두번째 요소가 30이 되고, 3번째 요소는 그 뒤의 메모리, 즉 뭔지 모를 값이 나오게 된다.
포인터의 활용 new
객체지향언어는 실행 시간에 동적으로 메모리를 할당받을 수 있다는 장점이 있다. 그리고 이렇게 동적으로 변하는 메모리를 다루는 도구가 포인터다.
구조체 역시 포인터로 생성 가능하며, 이때 new 예약어를 사용해야 한다.
#include <iostream>
using namespace std;
struct Human { // 구조체 생성
int age;
char name[20];
};
int main()
{
Human* human = new Human; // 포인터로 구조체 Human형식의 변수 생성
cout << "나이를 입력하세요";
cin >> human -> age; // 구조체 내부의 변수에 값 할당
cout << "이름을 입력하세요";
cin >> (*human).name; // 구조체 내부의 변수에 값 할당. -> 와 같은 동작
cout << "이름은 " << human->name << "입니다.";
}
이렇게 new로 포인터 변수를 사용했으면 이제 메모리를 해제해줘야 한다. 더이상 사용하지 않아 메모리 공간을 낭비하고 싶지 않으면, 포인터를 삭제해줘야 한다. 배열 역시 한번의 delete[] 함수로 해제가 가능하다.
#include <iostream>
using namespace std;
struct Human {
int age;
char name[20]; // 문자열을 직접 가리키는 포인터
};
int main()
{
Human* human = new Human;
cout << "나이를 입력하세요";
cin >> human -> age;
cout << "이름을 입력하세요";
cin >> (*human).name;
cout << "이름은 " << human->name << "입니다.";
delete human;
cout << "이름은 " << human->name << "입니다.";
}
위의 코드는 delete 이후의 human->name 에서 에러가 발생한다. human 의 포인터가 삭제되면서, human 의 메모리 주소가 아무것도 없기 때문이다.