C플플

From Hidden Wiki
Revision as of 17:21, 10 September 2018 by Onion (talk | contribs) (Created page with "[include(틀:프로젝트 문서,프로젝트=나무위키 프로그래밍 프로젝트)] * 관련 문서: 객체 지향 프로그래밍 ## 아래 예제 부분을 수...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

[include(틀:프로젝트 문서,프로젝트=나무위키 프로그래밍 프로젝트)]

* 관련 문서: 객체 지향 프로그래밍
    1. 아래 예제 부분을 수정 전 https://namu.wiki/thread/FvJjEZrBXTrRiojU99jmNU 토론을 확인하고 수정하시기 바랍니다.
    2. http://www.stroustrup.com/hello_world.c

{{{#!syntax cpp

  1. include <iostream>

int main() { std::cout << "Hello, world!" std::endl; } }}}

[include(틀:프로그래밍 언어)]

[목차]

개요

1983년 C 언어에서 직접적으로 파생된 프로그래밍 언어. 비아네 스트로스트룹(Bjarne Stroustrup)[* [] 발음을 자주 물어 보는지 아예 본인이 wav 파일로 읽는 법을 올려두었다.]이 1980년대 C 언어를 바탕으로 만든 언어다. 참고로 C 계열 언어에서 "++"라는 것은 1을 더해서 원래 변수에 대입하라는 뜻이다.[* 뭔소리인가 싶은 프로그래밍에 익숙하지 않은 사람들을 위해서 매우 간결하게 설명하자면 그냥 +1 정도 의미라 보면 된다. 수학교육과 등에서는 '다음수'라는 개념으로 가르친다.] 쓸 때는 C++라고 쓰고 읽을 때는 시 플러스 플러스, 혹은 시플플[* 실제로는 '씨뿔뿔'이나 '씨쁠쁠'로 발음되는 경우가 대부분이다. 참고로 이와 비슷한 경우로 '뿔테 - 플테' 사례가 있는데, 이쪽은 민간어원 때문에 엄연히 '잘못' 발음되는 경우.]이라고 읽는다. 연세가 꽤 있으신 교수님 중에는 간혹 시 더블 플러스라고 읽는 경우도 있다. 미국에서는 그냥 CPP라고 읽는다.

한국에서 컴퓨터공학과를 다닐 경우 배울 수 있는 프로그래밍 언어 3대장 중 하나이다. 나머지 둘은 예상했다시피 CJava.[* 컴퓨터공학과는 프로그래밍 언어를 배우는 학과가 아니기에, 전공과정에서 들어야 하는 순수한 언어 수업은 정말로 이 3개 정도가 끝이다. 물론 현 업계에서 사실상 필수로 알아야 할 언어들은 더 많지만, 시간의 압박 때문에 저 3개만 배운다. 물론 학교에 따라 과제와 졸작을 하다보면 능통하게는 아니어도 Python, JavaScript 정도는 다뤄볼 일이 있을 것이다. 너무 실망하지 말자.]

C와의 차이점

C의 문법에 OOP 개념을 추가하고 일반화 프로그래밍의 요소가 되는 STL을 붙였다. 그래서 대부분의 C 프로그램은 C++ 컴파일러에서도 문제없이 컴파일된다. 초기 C++ 컴파일러는 일단 C++ 코드를 C로 변환하고 그걸 C로 컴파일하는 방식을 사용했을 정도. 하지만 OOP나 일반화 프로그래밍이란 것은 단순한 문법이 아니라 코딩의 패러다임을 말한다. 그래서 C++ 방식으로 코딩하려면 해당 코드에서 C++에 새로 도입된 것을 추가하는 게 아니라 설계부터 시작해서 완전히 새로 해야 하는 경우가 많으므로, 초심자 입장에서는 서로 다른 별개의 언어로 보고 접근하는 것이 안전하다. 그래서 C로 프로그래밍에 발을 들어 놓은 후 C++/Java로 업그레이드(...) 테크를 타는 학생에게 C++ 프로그래밍을 해 오라 하면, C에서는 구조체라는 개념이 있더라도 잘해봐야 C++의 입출력 객체를 이용하는 정도를 넘지 못하고 절차적 프로그래밍을 그대로 따라가는 영락없는 C 스타일의 프로그램이 튀어나오기 일쑤다.

그 이유는 C++의 객체지향이 다른 객체 지향 언어에 비해 이해하기가 그렇게 만만한 개념이 아닌 데다가 C++의 객체지향은 C를 유지하면서 그대로 얹어놔서 뭔가 기묘하기 그지 없으므로 다른 객체지향 언어에서보다 잘 다루는데 더 많은 공부가 필요하다. 재밌는 것은, 반대로 C++ → C 테크도 만만치가 않다.[* C → C++은 절차지향 언어의 사고방식, C++ → C는 객체지향 언어의 사고방식이 머릿속에 굳어버리기 때문이다.] C++이 C의 모든 기능을 포괄하고 있으므로 C++을 할 줄 알면 C도 할 줄 안다고 생각하기 쉽지만, 사실 C++이 명시적으로 비교적 간단히 사용할 수 있도록 제공하는 기능들을 C에서는 암묵적으로 여러 가지 수많은 '트릭'을 통해서 쥐어짜내듯이 만들어 사용하는 경우가 많다.[* GNOME의 핵심 라이브러리인 Glib이 대표적으로 C 언어로 객체지향을 짜도록 구성되어 있다.] incomplete type declaration 트릭을 이용하여 캡슐화를 흉내내고, 매크로와 컴파일러 확장을 이용해서 type-generic function을 만들어 쓰고, struct hack을 이용하여 vector를 흉내 내는 식이다. 게다가, 저런 트릭은 언어 차원에서 정식으로 제공한다기보다 말 그대로 '트릭'에 가까우므로 이상한 조건들이 붙는 경우가 종종 있고, 그것들을 정확히 파악하고 있지 않으면 상당히 찾아내기 어려운 에러를 내는 경우도 많다. 말 그대로 C와 C++은 완전히 다른 언어로 파악하고 접근하는 것이 좋다. "잘 짜인 C 프로그램은 C++ 컴파일러로 컴파일할 수 있어야 한다"는 말도 C99가 나오면서 틀린 말이 되어버리기도 했고...

그래서 많은 대학에서 컴공 1학년 1학기 때 C를 먼저 가르치고 2학기에 C++를 가르치지만, 교수가 절차지향이 머리에 굳어버린다며 컴공에서 C 대신 C++와 객체를 먼저 가르치고 C는 아예 건드리지도 않고 다른 하드웨어 관련 학과에서만 가르치는 대학들도 많다. 객체지향만 배운다면 Python으로 가도 되지만, 포인터 등을 통해 메모리와 각종 Low Level적인 프로그래밍과 객체지향을 함께 배울 수 있기 때문이다. 컴공의 경우에는 C++를 모르면 2학년 부터는 강의를 전혀 이해할 수 없기 때문에 의외로 많은 학생들이 중도포기를 하게 되며 컴공을 나왔는데도 프로그래밍을 전혀 못하는 학생이 수두룩하다.

C++는 서식을 이용한 일반화 프로그래밍을 ~~악용~~[* C++의 템플릿을 모르고 보면 아예 이해불가이며, 템플릿을 배운 후 봐도 처음 보면 그 병맛에 입에서 WTF이 나오며, SFINAE (Function overloading을 함에 있어 조건에 따라 일부러 문법적으로 틀린 템플릿의 구현 코드를 발생시켜 틀리지 않은 문법이 되는 특정 overload만 선택되게 만드는 테크닉) 이나 expression template(템플릿을 재귀적으로 사용해서 lazy evaluation이 적용되는 효율적인 계산 코드를 컴파일시에 자동 생성하는 테크닉) 등 진정한 악용의 시점부터는 안드로메다를 느낄 수 있다.] 응용해서 컴파일 시점에 계산 등을 하는 TMP(Template Meta Programming)이라는 것이 존재한다. 배우기는 어렵고 알아보기도 힘들고 오류 찾기도 힘들지만 알아 두면 은근 써먹을 데가 많다. ~~하지만 여차하다가 바이너리 크기가 n배 증가하는 대참사가 벌어질 수도 있다.~~ ~~지금 성능이 눈 앞에 보이는데 바이너리 크기가 문제야?~~ 잘만 구현하면 실행 시간을 잃지 않으면서도 컴파일 시점에 다양한 처리나 계산이 가능하므로 라이브러리 구현에 종종 이용된다.[* e.g., 표준 라이브러리의 type 관련 부분, C++ 기반 수학 라이브러리들 등] 이는 C++ 템플릿의 고유한 기능[* C++ 템플릿이 코드를 컴파일 시점에 확장하는 방식이라는 것과, 비타입 인수도 줄 수 있다는 것을 이용한다.]을 이용하는 것으로 다른 언어에서는 비슷한 것도 찾기 힘들다.[* 참고로 자바나 C#에 있는 제네릭은 템플릿과는 아주 다르다. 자바로 TMP 같은건 꿈도 못꾼다. 당연히 작성하기는 제네릭이 훨씬 편하지만 (그리고 제네릭으로 하는 일은 C++에서 TMP가 아닌 일반적인 템플릿으로 작성한다) TMP의 의의는 컴파일 시간에 모든걸 해결하겠다는 진정한 성능덕질에 있다.]

C++에서의 객체지향

C++은 OOP를 지원하지만, C++의 객체지향은 다른 객체지향 언어에서와는 성격이 좀 다르다. 대부분의 객체지향 언어에서는 많은 부분을 런타임에 처리하며 메모리를 자동으로 관리하는 반면, C++에서는 최대한 많은 것을 컴파일 타임에 처리하는 것을 지향하며 메모리 등을 프로그래머가 직접 관리하게 하기 때문에 전반적인 클래스 디자인 자체가 상당한 차이를 보이게 된다. Java 등의 다른 객체지향 언어에서와 같은 방식으로 C++ 클래스를 디자인하면 거의 틀림없이 컴파일이 제대로 안 되거나 메모리 문제가 발생한다. 특히 GC를 지원하는 Java에서 C++ 테크를 탄 학생이라면 처음에는 메모리가 줄줄 새는 프로그램을 만들게 될 것이다. 반면 C++ 스타일로 다른 객체지향 언어에서 프로그래밍을 하는 경우 특별히 안 될 것은 없지만[* 소멸자가 호출되지 않는 등의 차이점은 있지만 심각한 문제가 되는 경우는 많지 않다.], 해당 언어의 스타일로 작성한 코드에 비해 시간이 많이 걸리고 너저분해 보이며 클래스 구조가 경직되어 수정하기 어려워진다.

대표적인 예가 함수 내부에서 객체를 동적으로 생성해서 그 포인터를 리턴하는 것. C++에서는 이는 메모리 문제를 일으키기 딱 맞는 방식이라서 클래스 디자인 단계에서 이런 종류의 함수가 필요없게 하기 위한 고려가 필요하지만[* 동적 할당을 해줬으면 해지도 해줘야 되는데, 클래스 사용자가 해줄 리가 없다(...)], 가비지 컬렉션이 자동으로 되는 언어에서는 매우 흔히 사용되는 방법이다. 이런 차이 때문에, Java, Smalltalk 등의 언어를 먼저 접한 프로그래머들은 C++의 객체지향이 짝퉁이라며 싫어하기도 한다.

이러한 차이가 생기는 것은 대부분의 객체 지향 언어는 직접적으로 Smalltalk의 영향을 받은 반면, C++는 Smalltalk보다 먼저 객체지향의 초보적인 개념을 제시한 시뮬레이션 전용 언어인 Simula에서 직접 영향을 받았기 때문이다. 이는 C 프로그램과의 호환성을 고려한 결과이기도 하지만, 기본적으로 C++에서 프로그램의 성능을 희생시키지 않기 위해서였다. Smalltalk의 경우 당시의 기술적 한계도 있고 해서 C보다 대체로 수십 배 정도 느렸고, 이는 C++에서 지향하는 결과가 아니었기 때문이다.

객체지향 등이 일반화되면서 프로그래밍 환경도 점차 중요한 개념을 언어 안으로 숨기고 사용자에겐 그것을 간편히 다룰 수 있는 인터페이스만 제공하는 추세로 흘러가고 있는데, 이런 방식은 일반적인 상황에서 생산성을 높이기는 좋지만 특정한 상황에서 속도를 높이기는 어렵다. 일반적으로 만들려면 필연적으로 많은 상황을 처리할 수 있도록 강력하고 복잡하게 만들어야 하기 때문이다. 따라서 특정 목적이 필요할 경우 언어에서 쌓은 추상화의 장벽을 뚫고 하위(low level) 개념을 이용할 필요가 있다. 아마도 이것이 어째서 메모리 관리를 알아서 해 주는 Java를 하면서 메모리 관리를 알아야 하고, 메모리 관리를 위해 C를 알아야 하고, C를 배우기 위해 하드웨어 아키텍처를 알아야 하는지에 대한 답일 것이다.

다만 이런 제한이 생기는 건 오래된 스타일의 C++ 코드에서나 그런 것이고, Modern C++에서는 스마트 포인터를[* 예를 들어 한 동적 객체를 여러 소유권자가 공유하는 경우 레퍼런스 카운팅을 지원하는 std::shared_ptr를, 단일 소유자만 존재하는 경우 std::unique_ptr를 사용한다.] move하는 방식으로 그들과 완전히 같은 문법이 구현 가능하기 때문에 더 이상 해당이 없는 사항이다.

성능

일반적으로 추상화 수준이 높은 언어일수록 프로그래머 머리로 해야할 구체적인 것들을 컴퓨터가 대신 해주고, 이것이 항상 최적화된 방식은 아니기 때문에 프로그램의 실행 속도가 상대적으로 느리게 마련이지만, C++ 프로그램은 성능 하락이 거의 없다. 좀더 정확히 말하자면 C 가 제공하던 머신컨트롤의 저수준 작업들을[* C 는 사실 유닉스 라는 OS를 만들기 위해 어셈블리 대체용으로 만들어진 언어라, 저런 머신컨트롤이 주된 임무 중 하나였다. 그리고, C++ 은 그 이름에서 보이듯이 사실상 C 를 대체하기 위한 언어였기 때문에 역시 저것들을 포기할 수 없었던 것이고.] 포기하지 않고 그대로 지원하면서 그 위에 여러 가지 추상적인 고수준 기능들을 집어넣어 추상적인 시스템 위에서만 노는 게 아니라, 저수준의 기계 제어까지 가능한 추상화라는 요상한 철학을 지지한다. 그래서, 자바 같은 언어들이 OOP를 구현하면서 동적 바인딩(가상 함수)을 디폴트로 쓰고 쓰레기 수집을 지원할 때 C++은 정적 바인딩을 디폴트로 하고 수동 메모리 관리를 유지한 것이다. 문제는, 저수준 제어와 고수준 추상화의 두 가지 개념은 서로 완전히 충돌하는 부분이 많기 때문에[* 추상화의 가장 큰 이유와 장점은 그것을 추상화시킴으로 해서 그 아래 감춰진 디테일한 부분을 신경쓸 필요가 없게 만드는 것이다.] 그러나, C++ 의 저수준 작업은 저런 디테일한 부분을 프로그래머가 신경끄지 못 하게 만든다. ~~그게 C++의 묘미이기도 하다~~ C++ 의 고수준 기능들은 C++ 방식으로 변형되어 적용되었거나 혹은 프로그래머가 저런 부분을 감안하여 사용해야 한다. RAII 등 독특한 C++만의 코딩 문화가 존재하는 것도 그 때문.

템플릿이 사용된 모든 타입에 대해 컴파일 시간에 확장하도록 설계된 이유 또한 실행 성능을 포기하지 않기 위해서이다. C++과 비슷한 정도의 기능을 가진 언어 중에서 C++만큼 빠른 실행 성능을 내는 언어 구현은 흔치 않다. 대신 프로그래머가 언어의 이상한 부분까지 신경쓰지 않으면 안 되는 디자인이 되어 제대로 쓰는 게 굉장히 어려운 언어가 되고 말았다.[* 대신 그만큼 섬세한 프로그래밍이 가능하다] 뭔가 딜레마같지만 C++과 비슷한 정도의 고수준 기능을 제공하는 언어는 절대로 C++보다 복잡하지 않다. 덤으로, 템플릿 같은 경우엔 실행 성능을 포기하지 않는 대신 컴파일 시간을 심각하게 포기했다. 심지어 디버깅도 힘들다. 다만 디버그 문제는 자기가 원하는 템플릿에 맞춰 중단점을 거는 게 가능해지는 등 많이 개선된 편이다. ~~아무도 안 알려줘서 문제지.~~

애초에 C 언어의 기능을 모두 포함했던 이유는 생산성과 함께 C 언어를 대체하겠다는 두마리의 토끼가 목적이었기 때문이다. 그러나, OS를 만드는 유닉스 커뮤니티들이 C++ 로의 전환을 거부해서 한마리 토끼는 놓쳤고... 그럼에도 자바라는 강력한 언어가 등장하기 전까지는 C 에 비해 압도적인 생산성으로 어플리케이션 소프트웨어 쪽에서 순식간에 대세언어가 되었으나...자바의 등장과 각종 스크립트 언어들의 부상, 그리고 비주얼 베이직에서 파이썬으로 이어지는 하이퍼 고 생산성 언어들의 등쌀에 현재는 포지션이 좀 애매해진 경향이 있다. 애초에 C 언어의 기능을 전부 포함했던게 공짜로 된것이 아니라, 그만큼 고급기능이 복잡해지는 ~~컴파일 속도도 엄청나게 느려지는~~ 역효과도 포함하고 있었고, 덕분에 자바나 기타 고생산성 언어들에 비해 생산성은 떨어지면서 정작 노리고 있던 C 언어의 대체도 날아간 상황.

현재는 클라이언트 쪽에서는 퍼포먼스가 엄청나게 중요하면서 동시에 개발속도도 크리티컬한 게임[* 사실 이것도 대형 게임에나 해당되는 말이고, 간단한 모바일 게임은 유니티 엔진의 사용 확대로 인해 C\#으로 많이 대체되었다.][* 아이러니한건, 유니티도 내부 소스는 C++로 이루어져있다는 사실이다. 즉, 스크립팅용으로만 C#을 쓰는 셈이다.], 포토샵, 웹 브라우저 등의 데스크탑 어플리케이션, 업무연속성이 중요한 금융권 IT망 및 금융공학에서 주로 사용된다. 사실 그 외에도 퍼포먼스를 중시하는 경우 여전히 많이 사용된다. 구글에서도 상당히 많이 사용하는 언어이다.[[1]] 이미 구글에서 개발한 언어인 Go가 나와 있었는데도 텐서플로우가 C++로 개발되었다는 점이 하나의 예시.

단점

분량이 너무 많아 중도포기 하기가 쉽다.

--장점: C-- --단점: ++--

'C++이 쉽다는 사람과는 상종하지 말라'는 말도 종종 보일 정도니... ~~90년대만 해도 그나마 쉬운 언어이긴 했다. 애초에 C를 배우고 C++을 배웠으니...~~ C++을 배우려는 초보자가 인터넷에 문의를 해보면 보통 초보자용 1개, 중급자용 1개, STL 1개 등등등 해서 여러 개 읽으라는 답변들이 많이 달리며, 개중에는 1000페이지 분량이 넘어가는 책들도 있다.[* 비아네 스트로스트룹이 직접 쓴 TCPL이 1300페이지, C++ Primer Plus가 1700페이지 정도를 자랑한다.] 물론 반드시 1000페이지짜리 책으로 공부해야 한다는 건 아니지만 C++ 교재들은 대체로 다른 언어 교재에 비해 두꺼운 편이다. 그나마 C++를 배우기 수월한 상황으로 가정해보자. 만약 C언어를 알고 있는 사람이 C++ 초보자용 교재를 1권 끝내고 프로그램을 만들어 보라고 해도 대부분 C 방식에서 벗어나질 못한다. C++을 편하게 사용하려면 STL까지 배운 다음 자료구조와 스트림, 템플릿 정도는 쓸 수 있는 상황에서 C++를 버무릴 줄 알아야 그나마 키보드에 손을 댈 수 있다. 이것은 절차지향에 따르는 C언어를 배우고 난 뒤 객체지향인 C++을 배우는 사람들의 고질적 문제로, 어찌 보면 당연할 수도 있다. C와 C++은 사실상 추구하는 설계구조부터가 상당히 다른 언어이니까.

C , C++ 중 어디가 쉽다라던가(...) 하는 건 어디까지나 간단한 프로그램의 예일 뿐이다. 둘의 설계구조가 다르고 성능상 미묘한 차이밖에 안난다. C의 함수구조에서는 다중의 인자값 전달이 필수적인데 구조체에 전부 때려박더라도 전역변수가 아닌이상 적어도 1개는 전달해야한다. 반면에 C++ 측은 클래스의 this를 활용하면 인자 전달없이 클래스에 속한 멤버함수 호출만 할 수 있다. 참고로 전역변수는 보통 단일객체인데 여러 이유들로 복수객체, 쓰레드세이프(thread-safe) 구조를 따르는게 일반적으로 좋다. 헤더참조 구조가 중복정의로 복잡해지는건 덤. Node.js 모듈구조를 참고 해보면 module.exports로만 다른모듈과 상호작용 할 수 있는데 C 계열은 헤더를 넣으면 그안에 있는 모든 건 상호작용되고 원치않으면 소스파일과 분리해야한다. --극한의 단점--

설상가상으로 한국에 발간된 C++ 책 중 모던 C++을 다루는 책은 매우 적어 더 힘들다. K&K나 K&R 하나만 가지고도 상당 부분을 익힐 수 있는 C언어와 비교해보라. 보통 이 언어 저 언어 손댄 프로그래머들의 책장에도 C++ 관련 서적이 가장 많은 경우가 많다. 언어가 난해하면 단순히 난이도가 높은 데서 끝나는 게 아니라, 저 진입장벽을 다 넘지 않은 프로그래머들이 많아진다는 것도 하나의 문제이다. 즉, 엉터리 코드가 범람하게 될 가능성도 높아지고 제대로 된 프로그래머를 찾기도 힘들어진다. C++ 비판론자들은 이 부분을 주로 공격하여 저수준부터 시작해서 고수준까지 기능은 엄청나게 많지만 설계단계에서 그걸 제대로 묶어주는 일관성을 잃어버린 실패한 언어라고 비판한다. 그래서 C++에서 할 수 있는 것을 다 할 수 있는, 좀더 쉬운 D라는 언어도 만들어졌지만 생각보다 인기가 별로 없는 듯.

리눅스 진영의 두 주축인 리누스 토르발스[* 초창기 리눅스 커널에서도 C++을 이용하려다 C가 낫다며 다시 돌아온 흑역사가 있었다.][* 리누스 토르발스의 말에 의하면, C++는 고도로 숙련된 개발자가 조심하면서 코딩을 하지 않으면, 망쳐버린다고 한다. 또 C++은 그래픽이나 의사코드를 짜기에는 너무 레벨이 낮고, C처럼 운영 체제 같은 시스템 프로그래밍에는 너무 추상화된 언어라고 한다. 출처: [[2]]]와 리처드 스톨먼은 둘 다 C++을 신랄하게 비판하였다. 일반적으로 토르발스와 스톨먼은 서로 앙숙관계라 엇박을 맞출 때가 많은데, C++을 비판할 때만은 한마음이 되었다.(...) 그럼에도 C++이 제공하는 기능들이 막강한지라, 리눅스 진영에서도 커다란 프로젝트에는 C++을 상당히 애용하고 있다.

최근 모질라 재단에서 C와 C++ 수준의 성능을 제공하면서도, 각종 메모리 관련 에러를 없앤 새로운 프로그래밍 언어 Rust를 개발 중이다. Rust는 파이어폭스Servo 엔진을 위해 만들어진 언어로, '소유권 이전'(C++에서의 move semantics와 비슷하다) 개념을 강제하여 메모리 관리를 보다 안전하게 만든 것이 특징이다. 다만 Rust는 메모리 오류를 컴파일 단계에서 차단하는 대신 컴파일러가 지나치게 엄격하여 C/C++를 쓰던 사용자 입장에서는 더 큰 불편함을 야기한다. 실무에서 C/C++가 Rust로 대체되는 사례는 많지 않을 것으로 예상된다.

역사

초창기

1979년 비아네 스트로스트룹이 느리지만 객체지향적인 언어 Simula의 컨셉을 C 언어에 접목시키면서 C with Classes라는 이름으로 만든 게 최초이다. 이후 1983년, 1989년, 1990년에 언어를 버전업하면서 이름이 C++로 바뀌게 된다. 이 시점에서 이미 클래식 C++의 틀은 완전히 잡혔다고 할 수 있다. 이때까지는 거의 스트로스트룹이 언어 개발을 전담하다시피 했고, 본인이 쓴 책 [C++ Programming Language]을 통해 C++라는 언어를 정의하고 레퍼런스 컴파일러를 배포하는 식으로 개발되었다.

표준화

이후 C++가 안정적으로 정착하고 수요가 폭증함에 따라 여러 회사에서 상업용으로 컴파일러를 만들었고, 이에 따라 코드가 컴파일러에 따라 중구난방이 되는 것을 막기 위해 표준화의 필요성이 제기된다. 그래서 ISO에서 스트로스트룹을 비롯한 프로그래밍 언어학자 및 컴파일러 제조사들을 모아 표준화 작업을 하기 시작한다.[* C++뿐 아니라 C, 파스칼 등 클래식 언어들이 전부 ISO에서 표준화되고 있다. 아예 이런 언어를 표준화하는 전문 태스크 팀 [[3]]라는 게 있으며, 이중 C++는 21번째 그룹에 속한다] 그렇게 1998년 최초로 표준안이 제정되었으며 이를 줄여 C++98[* 정식 명칭은 ISO/IEC 14882:1998]이라 부른다.

이후 2003년에 C++98 문서의 애매모호했던 부분들을 보완한 C++03[* 정식 명칭은 ISO/IEC 14882:2003]이 제정되었는데, 이는 그냥 표준화 문서상 불명확했던 것을 교정한 버전이다. 예를 들어 {{{std::vector}}}가 배열처럼 연속된 메모리를 차지하도록 표준에 명시했다. 사실 당시 컴파일러들 대다수가 이미 C++03 제정 이전부터 이러한 부분들을 잘 구현한지라, 실제 프로그래머 입장에서 변한 건 없다.

2007년에 표준 라이브러리를 확장하는 것을 골자로 하는 테크니컬 리포트가 제정되었다. 이름은 C++TR1[* 혹자는 이를 표준안과 동급으로 간주하고 C++07/TR1이라 부르기도 한다. 정식 명칭은 ISO/IEC TR 19768:2007.]이며, 표준화 이후 사실상 언어에 변화를 가한 첫번째 확장안이지만 엄밀한 표준이 아니라서 컴파일러 제작사가 원하면 넣고 아니면 마는 수준의 선택적인 확장안이었다. 그래서인지 전부 {{{std}}} 네임스페이스에 들어가 있지 않고 대신 {{{std::tr1}}} 네임스페이스로 분리되어 들어간다. 이후 이 TR1의 기능들은 C++11에 대부분 정식으로 흡수된다.

모던 C++

이후 10여 년간 별다른 변화 없이 쓰였으나, 2011년부터 최신 컴퓨팅 환경을 지원하기 위해 언어가 급격하게 변화하기 시작한다.

그 첫 단추를 끊은 건 2011년 8월에 제정된 새로운 ~~대규모 확장팩~~ 표준안 C++11.[* 정식 명칭은 ISO/IEC 14882:2011] 표준안 개발 당시 코드네임으로 C++0x라 불리었는데, 2000~2009년 중 언젠가 표준화가 될 것이라는 의미였다. 하지만 결국 2009년을 훌쩍 넘긴 2011년 8월에서야 정식 C++ 표준이 되어서 11이 붙었다. [[4]] 여담이지만 추가된 많은 기능 중 상당수 항목들이 boost 라이브러리의 판박이라[* 아예 boost 라이브러리 개발진 중 다수가 C++ 표준화 위원이기도 하다. 차세대 C++에 들어갈 요소를 표준화 위원들이 미리 개발해서 시험해본 것이라 봐도 무방.] 해도 과언이 아닐 정도로 많은 기능을 참조했다.

2014년 8월에 C++14[* 정식 명칭은 ISO/IEC 14882:2014]가 제정되었으며, 표준안 작성 당시 C++0x라 불리었던 C++11처럼 C++14도 C++1y라는 코드네임으로 불리었다. 주로 C++11에 추가된 요소들을 다듬고 확장하는 데 치중한, 비교적 마이너 표준안이다.

2017년 9월 6일, C++17 혹은 C++1z이 승인되었다. C++11의 요소들을 향상시키는데 주력했던 C++14에 비해, C++17은 언어 자체의 새로운 기능에 비교적 주력한다. 초안 단계에서부터 논란이 많은 표준안이기도 하다. C++11/14의 실정에 맞추어 옛날 기능을 삭제하자는 안이 많기 때문인데[* C++11 제정 당시에도 {{{std::auto_ptr}}} 등 많은 옛날 요소들이 deprecated로 명시되어 사용이 자제될 것을 권장받았으나, 이는 어디까지나 권고라 사용자가 맘 놓고 쓰려면 쓸 수 있었다. 이전 버전의 기능을 아예 죽여버린 사례는, C++98 시절에 실상 누구도 안 썼고 지금은 아예 용도가 바뀌어버린 {{{auto}}} 등 극소수만이 해당한다.], deprecated 판정을 받은 {{{std::auto_ptr}}}이나 삼중자(trigraph)[* C/C++의 특수기호는 미국의 부호체계인 ASCII를 기반으로 하고 있기 때문에 해당 영역에 다른 문자를 넣어 사용하던 유럽국가들의 코드페이지에서는 이상하게 표현되는 일이 있었다. 그래서 잘 사용하지 않는 문자의 조합으로 특수문자를 표기하는 방법. 문자 2개의 조합이면 digraph, 3개면 trigraph. 유니코드가 대세가 된 지금은 사실 필요 없고, 옛날 소스라고 해도 간단한 일괄 변환작업으로 새 표준에 맞출 수 있기도 하다. 다만 표준에서 삭제처리를 할 경우 해당 문법이 다른 기능으로 대체될 수 있기 때문에 일괄변환이 언제나 될 것이라는 보증이 안 되고, 후술하는 IBM 등 장기간의 낡은 코드와 관련된 이해관계자들 입장에서 떨떠름한 것은 사실.] 등을 삭제하자는 안이 이미 올라온 상태다. 이러한 삭제안이 통과될 경우 옛 코드에 대한 호환성을 포기하는 것이기 때문에, 10년 이상 된 코드들이 최신 컴파일러에서 컴파일되지 않을 가능성이 크다. 이것 때문에 IBM에서 문자체계의 문제를 내세워 삼중자를 제거하지 말라고 회사 차원에서 표준화 위원회에 진정서까지 제출했을 정도이다. [[5]] 하지만 후방호환을 위해 옛 언어 요소를 그대로 계속 두면 추후 표준안이 점점 비대해지는 것도 나름 문제이니 골치가 아픈 상황.

최종화된 C++17의 새로운 기능들은 [[6]] 정리되어 있다. 2017년 7월부터는 C++17을 보완하는 C++20의 표준안 논의를 시작한다고 한다.

각종 주요 컴파일러들과 모던 C++의 호환성은 [[7]] 볼 수 있다.

방언 및 확장

C++/CLI

.NET Framework의 CLR에 맞물려 동작하는 C++. 보통 프레임워크 정도로 제공되는 다른 라이브러리와 달리 .NET의 메모리 구조에 맞추어 언어 자체가 다르다.

초창기의 Managed C++은 정말 못 써먹을 언어였으나 그 후에 등장한 C++/CLI는 적어도 스펙상으로는 게임을 만들기에도[* 게임은 일반적으로 생산성이 매우 중요한 거대 프로젝트이면서 하드웨어의 성능을 극한까지 끌어내야 하는, 속도와 효율에 매우 민감한 특수한 소프트웨어 분야이기 때문에 프로그래밍 개념을 따질 때는 매우 중요하다. 괜히 이런 이야기에 게임에 대한 언급이 잘 나오는 게 아니다.][* 초기의 Managed C++은 언어의 포지션도 상당히 애매한 물건이었다. 간단히 말하자면 닷넷 프레임워크와 레가시한 운영체제 프레임워크를 동시에 지원할 작정이었는데... 결과물은 글자 그대로 이도저도 아닌 물건. 차라리 닷넷 프레임워크가 COM을 지원하니 그런 걸 쓰는 게 낫지...] 부족함이 없는 고속의 언어임에도 생산성은 C++에 비해서 높다고 한다. 특히 C#과 C++을 이어주는 래퍼 등의 모듈을 만들기에는 아주 제격이며, C/C++로 만들어진 프로젝트를 시간적 여유를 두고 닷넷 기반으로 바꾸는 용도로도 많이 쓰이고 있다. 필요에 따라 단계적으로 모듈을 바꿔치기 하다보면 어느새 순수 닷넷 애플리케이션 완성. 다만 지원 및 이식성이 떨어져서 업계 표준으로 쓰기에는 무리다.

여담이지만 .NET 출시 당시 마이크로소프트가 Managed 언어를 강력하게 밀어(C\# 등) 기존에 쓰이던 Win32 API C++나 MFC는 찬밥 신세라는 인상을 줬었다. 특히 닷넷 기술이 막 도입되던 Visual Studio 2005 당시 C++와 C#를 비교해 보면 대놓고 C++를 죽이려 한다는 느낌이 팍팍 들 정도. 하지만 이후 MS도 현실을 직시하고 VS 2008부터는 지원이 다시 강화되는 추세이며, C++11/14/17 지원 및 C++ AMP의 도입 등 여러가지 확장을 하고 있다.

CUDA

NVIDIA의 GPU에서 동작하는 C++ 기반 GPGPU 언어. 자세한 것은 해당 항목 참조.

OpenCL

개방형 GPGPU 언어. 원래는 C 기반이었으나 OpenCL 2.1부터 C++14를 기반으로 문법이 확장되었다. 자세한 것은 해당 항목 참조.

관련 문서

* 인라인 함수
* STL
* 템플릿

외부 링크

* [위키 사이트]
* [스트로스트룹의 C++11 FAQ]

분류:프로그래밍 언어분류:객체 지향 언어