안녕하세요 귀신입니다.
오랜만에 공부하려고 하니 정말 슬픈 소식이 생겼습니다.
바로 널널한 개발자님의 "독하게 시작하는 C프로그래밍" 강좌가
유튜브에서 내려간 걸 이제서야 확인했기 때문입니다.
c언어는 이제 익숙하지만 저는 이 강의가
무료강의인게 믿기지 않을정도로
정말 명강의였다고 생각했는데 여러 문제로
내리셨다고 하니 가슴이 아픕니다...ㅠㅠ 정말 명강의 중에 명강의였거든요ㅠㅠ
그와 동시에 또하나의 명저이자 명강의인 "이것이 C++이다"책의
강의 영상도 여름쯤에 내리신다는 공지사항을 읽었습니다.
그래서 강의가 내려가기 전에 제가 C++을 하면서
중요하거나 잘 잊어버리는 점들을
강의가 내려가도 확인할 수 있도록
정리를 해보려 합니다.
진짜 내려가면 안되는 강의인데 ㅠㅠ
그래서 Swift부터 하려다 급하게 C++부터 포스팅 할 것 같습니다 ㅠㅠ
여러분들도 강의 내려가기 전에 꼭 읽어보셨으면 합니다!
저는 당분간 C++관련 게시물은 아마
위 강의 내용을 복습하는 형식으로 진행할 것 같습니다.
그럼 시작하겠습니다.
1. 입출력 : cout과 cin
간단하게 입출력을 보겠다. 기존 prinf()함수나 scanf()함수와 다르게 굉장히 간편하면서 직관적이다.
우선 기본 출력은 cout, 입력은 cin으로 한다. 이 둘은 std라는 이름의 namespace에 속해있어 라인 2처럼
using namespace std; 라는 문구를 입력하면 앞에 std::라는 키워드를 생략해도 된다.
왜 기존 C의 입출력 함수보다 간단하다 표현했냐면 출력, 혹은 입력할 변수의 자료형을 생각하지 않아도 되기 때문이다.
printf()와 같은 C의 함수는 %d와 같이 일일이 서식 지정을 해줘야 했으나 이제 C++에서는 그런 귀찮음을 덜어도된다.
추가로 위에서 endl은 \n과 같이 한줄 띄어지는 코드이다. 물론 둘의 차이는 존재하니 궁금하면 검색해보시는 것을 추천한다.
2. 메모리 동적 할당 : new와 delete연산자
메모리 동적 할당도 굉장히 간편해졌다. 기존 malloc()함수와 new 연산자를 비교해보자.
기존 malloc()은 우선 앞에 포인터 자료형으로 형변환 해준뒤 매개변수로 자료형의 크기를 주어야했다.
(int*)malloc(sizeof(int)); 와 같이 말이다. 그러나 이제 new 연산자를 사용하면 C처럼 복잡하게 코딩할 필요가 없다.
int 하나면 그냥 new int, 여러개면 new int[5] 같이 배열처럼 사용하면 된다. delete연산자는 free()함수와 비슷하지만
반드시 배열로 할당된 메모리는 라인 17처럼 배열로 해제한다는 것을 주의하자.
3. 참조자
참조자는 정말 C++에서 중요한 기능이다. 우선 간단하게 참조나는 별명이라고 생각하면 좋을 것 같다.
우선 참조자는 기존 포인터와 다르게 &로 변수를 선언하며, 선언과 동시에 초기화 되어야 한다.
내부적으로 기능하는 것은 거의 포인터와 똑같다고 보면 된다.
위의 코드를 보면 참조자 r에 a를 대입했는데 이때부터 r은 a의 별명이 된다고 보면 좋다. 값을 바꿀 때 기존포인터처럼
*연산자같은 것을 쓸 필요도 없고, 그냥 a값을 바꿔도 r이 바뀌고 r값을 바꾸면 a값이 바뀐다.
그런데 단순 문법만 편해진다고 해서 참조자를 써야하는 이유가 될까? 기존 포인터 문법이 익숙한 사람들에겐
충분한 이유가 되지 못한다. 그러나 참조자에겐 이보다 더 중요한 기능이 있는데
바로 포인터가 가리키는 변수를 변경할 수 없다는 것이다.
이게 무슨 말이냐면 참조자 r이 현재 a를 가리키고 있는데, 참조자는 여기서 다른 변수를 가리킬 수 없다.
즉 포인터에 const 키워드를 붙인 기능이다. 다음 코드를 보자.
우선 설명하기 전 const 위치에 따른 차이점을 살펴보자
라인 6과 같이 하면 포인터가 가리키는 곳의 값을 변경하는 것을 금지한다.
무슨 말이냐면 *p = 10; 과 같은 코드가 안된다는 말이다.
그러나 값의 변경은 불허해도 가리키는 곳을 변경하는 것을 허용한다.
라인 10처럼 p = &b와 같은 코드는 가능하다.
라인 7과 같이 const를 위치시키면 가리키는 곳의 값은 변경할 수 있지만, 가리키는 것을 변경할 수 없다.
즉 라인 6과 반대다.
라인 12, 13을 보면 *q = 20; 처럼 값을 변경할 수는 있지만, q = &b처럼 가리키는 곳은 변경하면 에러가 발생한다.
참조자는 라인 7과 같다. 한번 가리키는 곳을 정하면 절대 그 곳을 변경할 수 없다.
그러나 그 주소의 값은 변경할 수 있다.
참조자는 보다 간편한 문법으로 라인 7의 기능을 하므로 간단하게 안전성을 확보할 수 있다.
포인터가 가리키는 곳을 바꿨을 때 위험한 경우 중 하나는 메모리 동적할당을 사용할 때이다. 다음 코드를 보자.
메모리 동적 할당 역시 포인터 변수를 사용한다.
동적할당한 메모리를 가리키는 포인터 변수가 임의로 다른 곳을 가리키게 할 수 있는데,
이 때 치명적인 에러가 발생한다. 동적할당한 메모리 외에 다른 곳을 가리키게 되면
free()함수를 사용할 때 문제가 생기기 때문이다.
그 이유는 메모리를 해제해야 하는데 포인터 변수가 엉뚱한 곳을 가리키고 있어 해제를 못하기 때문이다.
이같은 위험성을 참조자는 문법과 그 기능으로 처음부터 없애주고 있다. 그렇기 때문에 참조자를 자주 사용하길 바란다.
4. auto 키워드와 범위기반 for문
auto 키워드는 정말 간편한 키워드이다. auto는 대입 받는 변수의 자료형으로 자동 설정 해주기 때문에 사용자 입장에선 굉장히 편하다. 위의 코드를 보면 auto b = a;처럼 하게되면 b의 자료형은 a를 따라 자동으로 int로 정해진다.
따라서 사용자는 대입하려는 변수가 어떤 자료형인지 일일이 확인하지 않고 그저 auto를 사용해 간단하게 변수를 설정할 수 있다. 여기서 더 엄청난 것은 auto로 인해 C에선 상상도 할 수 없는 기능이 가능해 진다는 것이다.
바로 범위 기반 for문인데 다음 코드를 보자.
위 코드의 라인 6을 보자. for문 블록의 지역변수 n을 auto 키워드로 선언하였다. 위의 구문같이 하게되면
반복문의 반복 횟수는 자동적으로 aList의 크기만큼 돌아가게 되며 n의 값은 aList의 배열 요소의 값이 들어가게 된다.
파이썬을 해본 사람이라면 for n in aList와 같다고 생각하면 된다.
이 같이 기존 반복문을 돌릴 때 sizeof()연산자 등을 활용해 배열크기만큼 반복 횟수를 정해줘야 했던 기존 코드와
비교해 정말 간편하게 배열에 관한 반복문을 짤 수 있게 되었다.
추가적으로 헷갈릴 부분을 살펴보면 auto n은 단순 변수이므로 n에 0을 대입한다고 해서 원본 aList에는 전혀
영향을 끼치지 못한다. 그러나 다음 코드를 보자.
위의 코드를 보면 auto &n과 같이 기술하였는데, n을 참조자로 선언한 것이다. 이와 같은 코드는 결국 aList원본에 접근할 수 있게 하여 n에 0을 대입하면 aList의 요소값도 0으로 바뀌게 되고 아래 콘솔창과 같이 출력되는 것이다.
auto키워드는 정말 프로그래머에게 간편한 기능이므로 앞으로 코딩하면서 자주 사용하도록 습관을 들이면
분명 유리할 것이라 생각한다.
5. 마무리
우선 C++ 첫번째 포스트는 이렇게 마무리하려한다. 아마 이미 한번 책과 강의를 정독한 적이 있어서 위와 같이 간단하게만 설명하고 넘어가려 한다. 필자가 블로그를 하는 이유는 복습과 내가 필요하고 까먹었을 때마다 들어와서 확인하는 용도이기 때문이다. 이것이 C++이다 강의가 내려간다고 하니 하루빨리 전 강의 내용을 복습해서 블로그 포스팅을 해야겠다. C++이란 언어는 내가 지금까지 써봤던 언어 중 가장 어려우면서도 매력적인 언어같다. 공부하면 할수록 너무 알아야할게 많지만 그만큼 공부했을 때 너무 재밌다. 난 C++이 제일 재밌는 것 같다. 여기까지 블로그 읽어주신 분이 계신다면 감사를 표하며 이만 글을 마치겠다. 빠이.
참고자료
https://youtube.com/playlist?list=PLXvgR_grOs1DFOWF65X0Zqnd_264x41u-
'C++' 카테고리의 다른 글
C++ 복사생성자 : 얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy) (0) | 2022.03.17 |
---|---|
C++ 세번째, 생성자와 소멸자 그리고 this 포인터 (0) | 2022.03.08 |
C++ 두번째, 클래스(Class) 기본 개념과 접근 제어 지시자 (0) | 2022.02.23 |