* 블로그에 작성된 따라배우는 C++ 관련 모든 코드와 사진들의 저작권은 강의의 저자이신 홍정모 교수님께 있습니다.
인프런 사이트(www.inflearn.com)의 '홍정모의 따라하며 배우는 C++' 유료강좌를 실제로 구매하였고
강의를 수강하며 제 스스로 복습 및 내용 정리를 위해
강의에 나오는 코드들을 따라친 코드와 교수님의 말씀, 그리고 강의에 나오는 사진들을
활용하였음을 미리 알립니다.
마지막으로, 좋은 강의를 제작해주신 홍정모 교수님께 감사드립니다.
______________________________________________________________________________________________
배열의 이름은 배열의 첫 원소의 주소값이다. 근데 메모리 관점에서 봐서는 당연하다.
첫 원소부터 값들을 읽으면서 배열에 접근하니까.
그렇기에 배열의 이름에 *을 하면 첫번째 원소값이 나온다.
배열을 인자로 받을 때 포인터로 받는다는 것은 이제 알 것이다.
하지만 구조체의 경우 구조체를 인자로 보내면 구조체 전체가 복사되는 형태로 전달된다.
그게 싫다면 구조체 포인터를 활용하면 되겠지.
배열이 좀 특수한 경우로 포인터로 인자가 전달된다라는 것을 인지하자.
주소값에 연산을 이용할 수도 있다.
주소값에 +1, -1을 한다는 의미는 가리키는 변수의 크기만큼 이동(shift)한다.
배열도 결국엔 배열 요소들의 각 값마다 일정 크기들을 할당받고 있으니 저렇게 주소값의 간격이 일정.
주소값의 연산을 통해 표현이 가능하다.
배열의 이름이 첫번째 원소의 주소값이라 했으니 주소값의 연산을 이용해 *로 접근가능.
지금도 헷갈리는 부분이다. 그래서 잘 정리해보자.
우리가 R-value에 문자열을 적어주면 이건 말 그대로 상수다. 변경이 불가능한 문자열이다.
그렇기에 포인터로 접근하더라도 const를 선언해주는게 맞다. 이 문자열이 변경되선 안되기 때문이다.
좀 특이한 부분이다. 문자배열이랑 문자열의 경우 그냥 어떻게 보면 주소값을 준 것에 불과한데
열들이 나온다. 그냥 처음에 char[]이랑 char*으로 선언한 것이기에 cout에서 이거 문자열아냐? 생각하면서
한번 확인해본다는 측면인듯.
동적 할당에 대해 배웠다.
new를 이용해 메모리를 할당받고 해당하는 메모리의 주소를 return 하기에 포인터로 받아야한다.
또한 new로 메모리를 할당받으면 반드시 추후에 delete로 해제해야한다.
new와 delete은 바로 할당하고 해제되는게 아니라
new의 경우 사용 가능한 메모리가 있는지 한번 확인을 해야하고 delete의 경우도 할당받은 메모리를 지우러 가야하기 때문에 느릴 수 있음.
만약 그렇다면 배열을 동적할당 받고 싶다면?
배열이니까 []붙이면 되겠지.
해제할 경우
delete[] 변수명을 하면 된다.
첫번째 경우 int* 앞에 const가 붙었기에 포인터로 접근하는 값을 변경할 수 없다.
두번째 경우 ptr 즉 주소값 앞에 const가 붙었기에 가리키는 변수가 바뀌어선 안된다. 주소값이 바뀌기 때문에.
그리고 포인터와는 또 비슷하면서도 다른 참조에 대해 배웠다.
참조는 "별명"이다.
쉽게 생각하면 해당 변수의 또 다른 이름이다.
그렇기에 주소값들을 찍어보면
int* ptr = &value;
int& ref = value;
value와 ref는 같기 때문에 주소값이 서로 같은 것이고
ptr은 value의 주소값을 저장하기에 ptr도 같지.
&ptr은 아예 다른 변수니까 다르고.
참조의 경우 포인터와 다르게
int* ptr = nullptr;
ptr = &value; 이렇게 두 줄로 구분이 불가하다.
왜냐하면 참조를 할 때 처음부터 어떤 변수를 참조할 거에요 라는 걸 명시해야하기 때문이다.
그리고 참조하는 변수가 const로 상수처리가 되어있다면 단순 참조로는 불가하다.
내가 참조로 그 변수의 값을 변경할 수 있기 때문이다.
또한 참조의 경우 가리키고 있는 변수를 변경도 가능하다.
우리가 인자를 그냥 값으로 보낼 경우 main함수의 n과 doSomething함수의 n은 엄연히 다른 변수이다.
하지만 인자를 ref로 받는다면? 참조니까 같은 변수이기에 값이 변경이 되겠지.
참조이니 당연히 같은 변수니까 주소값도 같겠지.
참조를 배열로 받으려면?
int& arr[]형태로.
참조를 주로 언제쓰냐?
구조체의 경우 구조체 안의 구조체 이런 형식이면 .을 사용할 경우가 많아 복잡해진다.
근데 이럴 때 참조를 활용하면 간단하게 해당 값에 변경이 가능하다.
구조체의 참조면 멤버 접근이 당연히 .지만
포인터의 경우면 -> 또는 *(). 으로 접근하지.
for each 구문의 경우 꽤 유용하다.
배열의 첫 값부터 끝까지를 쭈욱 도는 것이다.
for each 구문의 경우 주의해야할 것이 단순 값을 인자로 넣을 경우 그냥 그 값을 복사해서 사용하기에 변경이 불가능하다.
그래서 참조를 매우 자주 사용한다 for each 구문에.
void pointer의 경우 내가 어떤 형태의 변수를 가리킬 지 정해지지 않았을 때 사용한다.
변수 형태가 정해져있지 않았기에 주소값의 연산을 하면 내가 몇 바이트를 이동할 지 모르니 오류가 난다.
void pointer를 사용한 후 값을 가리킨 후 값을 출력하려면 static_cast로 자료형태를 명시해줘야한다.
std::array의 경우 정적 배열을 선언할 때 사용한다. 단순히 int arr[]로 하는 것보다 좋은 이유는
여러 구현된 함수들을 사용할 수 있기 때문이다.
size, resize, begin 등의 여러함수들을 유용하게 사용할 수 있다.
다만 std::array의 경우 인자로 보낼 때 포인터가 아닌 인자로 보내지기 때문에
변경을 하고 싶은 경우 포인터나 참조를 활용해야한다. 이게 단순 정적배열과는 다르다.
vector의 경우 동적 할당 배열을 할 때 주로 사용한다.
vector의 좋은 점은 마찬가지로 여러 함수들을 활용할 수 있고
기존의 동적할당은 delete을 무조건 수기로 작성해줬어야함에 비해
vector는 알아서 delete을 해주기 때문에 편하다.
그리고 길이를 스스로 알고 있기 때문에 함수의 인자로 줄 때 함수의 길이를 줄 필요가 없다.
'C++(따라하며 배우는 C++)' 카테고리의 다른 글
Chapter 7-(4). 함수 (0) | 2021.09.07 |
---|---|
chapter 7-(3). 함수 (0) | 2021.09.06 |
chapter 7-(2) . 함수 (0) | 2021.09.04 |
Chapter 7-(1). 함수 (0) | 2021.09.02 |
chapter 6-(1). 행렬, 문자열, 포인터, 참조 (0) | 2021.08.31 |