CppCon 2015 - "Stop Teaching C" (Kate Gregory)

시작하기에 앞서

“Stop Teaching C” 토크는 C++ 컨퍼런스인 CppCon에서 Kate Gregory가 발표한 토크의 제목입니다.

C 언어를 쓰지 말라는 의미가 아니라, C++을 가르치는데 C처럼 가르치지 말라는 의미입니다.

C 언어는 좋은 언어입니다. 오해가 없길 바랍니다 ㅎㅎ,,

 


C->C++ 공부 방법이 만드는 문제

현재 많은 C++ 커리큘럼들이 C를 먼저 공부한 후 C++을 공부하는 방향을 지향합니다.

이는 두 언어가 상당히 비슷해 C를 아는 사람에게 C++을 가르치기 쉽기 때문입니다.

상당수의 현업 C++ 유저들이 C++이 생겨나기 전 C를 먼저 사용하다가 넘어온 경우가 많은데, 본인들이 겪은 공부 과정을 전수하기 위해 이 방법을 사용하기도 합니다.

하지만 이 방법을 채택하면 제대로 된 C++를 공부하는데에 더 오랜 시간이 걸리게 됩니다.

 

C와 C++에는 극명한 차이가 있습니다.

C에는 RAII, type-safety, template, lambda, exceptions, iterator와 같은 기능이 없습니다.

C로는 Object-oriented design을 공부할 수 없습니다.

C를 먼저 배운 후 C++을 공부하게 되면, 이미 익숙해진 C스타일을 버리고 C++을 새롭게 공부해야합니다.

그럴바에는 Day 1 부터 C++ 스타일을 공부하는게 더 효율적일 겁니다.

 


C++ 코스 Day 1에 가르쳐서는 안될 것들

아래에 있는 내용들은 ‘C++에서 쓰면 안되는 것들’이 아닙니다.

C++을 공부하는데에 Day 1에 가르치면, 공부하는 사람 입장에서 굉장히 헷갈리게 되는 것들입니다.

대학교에서 C++ 코스를 듣고 ‘와 에반데- C++은 내 길이 아닌가보다’ 하고 생각하게 만드는 것들입니다.

char* string

char*로 string을 다루기 위해서는 pointer를 이해해야합니다.

기본적인 Hello world까지야 printf()sscanf()로 어떻게든 됩니다.

하지만 조금만 더 깊게 들어가 string을 다루기 위해서는 1. char array에서 pointer를 이동하는 방법, 2. off-by-one error 이해, 3. null terminator의 대한 개념까지 이해해야합니다.

그 이후에 구현을 위해 여러가지 C에서 제공하는 string 함수들을 외워야합니다 (e.g. strcmp()).

5분만 들어도 ‘와 쓰읍 C++은 어렵구나’라고 생각하게 만드는 주범 입니다.

해결책

C++ 방식으로 처음부터 가르치면 char* 대신에 <string>을 사용할 수 있습니다.

<string>char*에 비해 이해하기 훨씬 쉬우며, Python이나 javascript와 같이 string이 built-in 기능으로 포함되어있는 다른 프로그래밍 언어를 겪은 사람들은 string을 곧바로 이해할 수 있습니다.

1980~년대에 공부하신 분들은 char*로 배우셨을 텐데, 이는 그 당시에 <string>이라는 기능 자체가 최신 기능처럼 느껴졌을 것 이기 때문입니다. (그리고 2021년 현대에 string은 그냥 어디에든 있는 기본 기능입니다)

<string>을 사용하면서 C++의 강점인 operator overloading과 strong type을 소개할 수도 있습니다.

1
2
3
4
5
6
7
#include <string>

string name;
// ...
string greeting = "Hello, " + name;
if (name == "Kate")
greeting += ", I know you!";

 

printf

변수의 값을 확인하기 위해 printf()를 가르칩니다.

printf()를 사용하기 위해서는 format specifier를 다 외워야합니다.

그리고 많은 경우 초보자들은 format specifier로 인해 에러를 경험합니다. (e.g. %c vs %s)

오전 10시 반 Day1 C++ 클래스를 들으면서, 초보자들은 벌써 복잡한 에러메세지를 마주하며 본인이 짠 간단한 프로그램의 변수 값도 확인하지 못하게 됩니다.

해결책

Debugger를 써서 코드 한줄한줄 넘어갈 때 변수 값이 어떻게 바뀌는지 보여줍시다.

실제로 출력도 해야하는 경우에는 cout, cin, cerr로 빠르게 결과를 보여줍시다.

stream 방식을 사용할 경우 속도가 좀 느려질 수 있다는 걸 언급만 하고 넘어가도 괜찮습니다.

Day1 이니까요.

 

[] arrays

char*와 비슷하게, 초보자에게 array의 기본 기능을 가르치기도 전 부터 포인터 개념을 요구합니다.

기본적으로 address와 reference의 개념을 익혀야하고, 그 후 bounds checking, off-by-one 과 같은 에러에 부닥치며, array를 익히기도 전에 여러가지 개념을 헷갈리기 시작합니다.

심지어 대부분의 [] array를 사용한 예제는 더 쉽게 적을 수 있는 방식이 있음에도 raw for loop 내부에 알고리즘을 직접 구현하는 방식을 씁니다.

예를 들어, “이 array 안에 3이 몇개가 있을까요?”라는 문제를 푸는 코드를 작성할 때, 쉽게 하려면 range-based for loop를 써서 가독성을 높이거나, 또는 std::count를 쓰면 됩니다. raw for-loop에서 i 값 하나하나 세면서 하지 말구요.

해결책

std::vector를 쓰면 됩니다.

초심자에게는 std::vector로 거의 모든 케이스를 커버할 수 있습니다.

기본기를 익히고나서, 성능이 중요하게 될 때 STL에 성능을 개선할 수 있는 다른 형태의 자료구조들이 존재한다고 알려주기만 해도 충분합니다.

하지만 처음부터 iterator를 알려주는건 추천하지 않습니다.