[이것이 C++이다] Part 01. C에서 C++로 문법 전환하기 (2)
1.5 메모리 동적 할당
- malloc()과 포인터
- malloc()은 주어진 크기(size_t)만큼 메모리를 빌려 주소를 반환하는 함수로 메모리의 “크기” 외 신경을 쓰지 않는다. 용도? malloc() 관점에서는 중요하지 않다.
- 포인터는 가리키는 대상 보다 접근자의 해석이 더 중요한 문법이다. 예를 들어, int형 포인터 변수(int *a)는 가리키는 대상이 어떠하든 int 형태로 해석한다.
즉, malloc()과 포인터는 사용자의 자유도가 높은 문법으로 “잘 알고 사용”해야 한다.
new, delete
-
new 연산자는 malloc()과 다르게 메모리 크기를 정하지 않는다는 특징이 있다.
#include<iostream> int main() { // 인스턴스만 동적으로 생성하는 경우 int *pdata = new int; // 초깃값을 기술하는 경우 int *pNewData = new int(10); *pdata = 5; std::cout << *pdata << std::endl; std::cout << *pNewData << std::endl; delete pdata; delete pNewData; // 5 // 10 }
-
배열 형태로 동적 생성한 것은 반드시 배열 형태로 삭제해야 한다.
int *arr = new int[5]; delete[] arr;
-
new 연산자는 객체의 생성자를 호출하고, delete 연산자는 객체의 소멸자를 호출한다.
1.6 참조형
참조자
- 변하지 않는 포인터와 같다. (scope 끝까지)
- 반드시 선언과 동시에 초기화 해야 한다.
- 상수에는 포인터를 선언할 수 없는 것 처럼 참조도 사용할 수 없다.
-
포인터와 참조는 내부 구조상으로 동일하다.
int ndata(10); int &rdata(ndata); // rdata, ndata 이 두 주소가 같다. rdata = 5; // 원본인 ndata값이 5로 바귄다. int *pdata = &3; // 포인터는 상수를 가리킬 수 없으므로 불가능 int &rdata(3); // 상수에 대한 참조는 불가능 int &rdata; // 참조 원본이 없으므로 불가능
참조자를 왜 쓰는데?
-
덩치 큰 자료는 값을 넘겨주는 것 보다 주소(C++에서는 ‘참조’)를 넘겨 주는 것이 효율적이다.
void TestFunc(int &rParma) { rParam = 100; // 원본 변경 } int main() { int nData = 0; TestFunc(nData); // 여기서는 매개변수가 참조인지 알 수 없다. std::cout << nData << std::endl; } // 100
- r-value 참조
- 곧 사라질 대상에 대해 참조자를 부여한다.
- 변수와 상수 포함.
int &&rdata = 3+4;
1.7 범위 기반 for문
-
참조자 형식으로 선언해야 for문 내에서 배열의 요소 변경이 가능하다.
int nlist[5]; for (auto n : nlist) { // nlist 접근만 가능 } for (auto &n : nlinst) { // nlist 변경 가능 }