C++는 국제 표준화 기구(ISO)에 의해 표준화되었으며, 최신 표준 버전은 2024년 10월 ISO/IEC 14882:2024(비공식적으로 C++23)로 승인 및 발표되었다. C++ 프로그래밍 언어는 1998년에 ISO/IEC 14882:1998로 처음 표준화되었으며, 이후 C++03, C++11, C++14, C++17, C++20 표준에 의해 개정되었다. 현재의 C++23 표준은 새로운 기능과 확장된 C++ 표준 라이브러리로 이전 표준들을 대체한다. 1998년 첫 표준화 이전에는 비야네 스트롭스트룹이 1979년부터 벨 연구소에서 C 언어의 확장으로 C++를 개발했다. 그는 프로그램 구성을 위한 고급 기능을 제공하면서도 C와 유사하게 효율적이고 유연한 언어를 원했다. 2012년부터 C++는 3년 주기의 릴리스 일정을 따르고 있으며, 다음 표준으로는 C++26이 계획되어 있다.
1979년, 덴마크의 컴퓨터 과학자비야네 스트롭스트룹은 C++의 전신인 "클래스를 포함한 C"에 관한 연구를 시작했다. 새로운 언어를 만들게 된 동기는 스트롭스트룹이 박사 학위 논문을 위해 프로그래밍을 했던 경험에서 비롯되었다. 스트롭스트룹은 시뮬라가 대규모 소프트웨어 개발에 매우 유용한 기능들을 가졌지만 실제 사용하기에는 너무 느리다는 점을 발견했고, 반면 BCPL은 빠르지만 대규모 소프트웨어 개발에 적합하지 않을 정도로 너무 저급 언어라는 점을 발견했다. 스트롭스트룹이 AT&T 벨 연구소에서 일하기 시작했을 때, 그는 분산 컴퓨팅과 관련하여 유닉스커널을 분석하는 문제에 직면했다. 박사 과정 시절의 경험을 떠올린 스트롭스트룹은 C 언어에 시뮬라와 같은 기능을 추가하여 강화하기로 결정했다. C는 범용적이고 빠르며 이식성이 높고 널리 사용되었기 때문에 선택되었다. C와 시뮬라의 영향 외에도 알골 68, 에이다, CLU, ML 등의 다른 언어들도 이 새로운 언어에 영향을 주었다.
처음에 스트롭스트룹의 "클래스를 포함한 C"는 C 컴파일러인 Cpre에 클래스, 파생 클래스, 강한 타이핑, 인라이닝, 디폴트 인수 등의 기능을 추가했다.
2015년 파리에서 진행 중인 C++11 기능에 대한 퀴즈
1982년, 스트롭스트룹은 여러 이름을 거쳐 "C++"라고 이름 붙인 "클래스를 포함한 C"의 후속 언어를 개발하기 시작했다(++는 C의 증감 연산자이다). 가상 함수, 함수 및 연산자 오버로딩, 참조, 상수, 타입 안전한 자유 저장소 메모리 할당(new/delete), 개선된 타입 체크, 그리고 두 개의 슬래시(//)를 사용하는 BCPL 스타일의 한 줄 주석 등의 새로운 기능이 추가되었다. 또한 스트롭스트룹은 C++를 위한 새로운 독립형 컴파일러인 Cfront를 개발했다.
1984년, 스트롭스트룹은 최초의 스트림 입출력 라이브러리를 구현했다. 이름이 붙은 출력 함수 대신 출력 연산자를 제공하자는 아이디어는 더글러스 매킬로이에 의해 제안되었다 (그는 이전에 유닉스 파이프를 제안한 바 있다).
1985년, C++ 프로그래밍 언어의 초판이 출간되었는데, 당시에는 아직 공식 표준이 없었기에 이 책은 언어의 결정적인 참고 자료가 되었다. 같은 해 10월, C++의 첫 번째 상용 구현체가 출시되었다.
1989년에는 C++ 2.0이 출시되었고, 이어 1991년에는 C++ 프로그래밍 언어의 개정된 2판이 출간되었다. 2.0의 새로운 기능에는 다중 상속, 추상 클래스, 정적 멤버 함수, 상수 멤버 함수, 보호된 멤버(protected members)가 포함되었다. 1990년에는 Annotated C++ Reference Manual이 출간되어 미래 표준의 기초가 되었다. 이후 추가된 기능으로는 템플릿, 예외 처리, 이름공간, 새로운 캐스트, 불리언 자료형 등이 있다.
1998년 C++98이 출시되어 언어가 표준화되었으며, 2003년에는 마이너 업데이트인 C++03이 출시되었다.
C++98 이후 C++는 비교적 천천히 발전하다가, 2011년에 C++11 표준이 발표되면서 수많은 새로운 기능이 추가되고 표준 라이브러리가 더욱 확장되었으며 C++ 프로그래머들에게 더 많은 편의를 제공하게 되었다. 2014년 12월에 발표된 마이너 업데이트인 C++14 이후, C++17에서 다양한 새로운 기능들이 도입되었다. 2020년 2월에 마무리된 후, C++20 표준 초안이 2020년 9월 4일에 승인되었고, 2020년 12월 15일에 공식적으로 발표되었다.
2018년 1월 3일, 스트롭스트룹은 "C++ 프로그래밍 언어를 구상하고 개발한 공로"로 2018년 공학계의 노벨상이라 불리는 찰스 스타크 드레이퍼상 수상자로 발표되었다.
2022년 12월, C++는 TIOBE 지수에서 지수 역사상 처음으로 자바를 제치고 3위를 차지했다. 2024년 11월 기준[update], C++는 파이썬에 이어 2위를 기록하고 있으며 자바는 3위이다.
2025년 3월, 스트롭스트룹은 언어 커뮤니티에 C++를 방어해 달라는 요청을 보냈다. C++는 수동 메모리 관리를 허용하기 때문에 프로그래머가 실수로 잘못 사용할 경우 버퍼 오버플로와 같이 보안 위험을 초래하는 버그가 프로그램에 유입될 수 있기 때문이다.
어원
스트롭스트룹에 따르면, "이 이름은 C로부터의 변화가 진화적 성격을 띠고 있음을 의미한다." 이 이름은 릭 마시티(Rick Mascitti, 1983년 중반)가 지은 것으로 알려져 있으며 1983년 12월에 처음 사용되었다. 1992년 마시티는 명명 이유에 대해 비공식적인 질문을 받았을 때, 익살스러운 기분으로 지은 것이라고 답했다. 이 이름은 변수의 값을 증가시키는 C의 ++연산자와, 강화된 컴퓨터 프로그램을 나타내기 위해 "+"를 사용하는 일반적인 명명 규칙에서 유래했다.
개발 기간 동안 C++는 최종 이름을 얻기 전까지 "새로운 C"(new C)나 "클래스를 포함한 C"로 불리기도 했다.
철학
C++가 존재해 온 기간 동안 그 개발과 진화는 일련의 원칙들에 의해 가이드되어 왔다.
실제 문제에 의해 주도되어야 하며 그 기능들은 실제 세계의 프로그램에서 즉각적으로 유용해야 한다.
모든 기능은 구현 가능해야 한다 (상당히 명확한 방법으로).
프로그래머는 자신만의 프로그래밍 스타일을 자유롭게 선택할 수 있어야 하며, C++는 그 스타일을 완전히 지원해야 한다.
유용한 기능을 허용하는 것이 발생 가능한 모든 오용을 방지하는 것보다 더 중요하다.
프로그램을 별도의 잘 정의된 부분으로 조직하는 기능을 제공해야 하며, 별도로 개발된 부분을 결합하는 기능을 제공해야 한다.
자료형 체계의 암시적 위반이 없어야 한다 (하지만 프로그래머가 명시적으로 요청한 경우에는 명시적 위반을 허용한다).
사용자 정의 타입은 내장 타입과 동일한 지원과 성능을 가져야 한다.
사용되지 않는 기능은 생성된 실행 파일에 부정적인 영향을 미쳐서는 안 된다 (예: 성능 저하).
C++는 JTC1/SC22/WG21로 알려진 ISO 작업 그룹에 의해 표준화된다. 이 작업 그룹은 매년 3회의 일주일짜리 회의를 개최한다. 지금까지 일곱 번의 C++ 표준 개정판을 발표했으며 현재 다음 개정판인 C++26을 작업 중이다.
1996년 스톡홀름에서 열린 C++ 표준 위원회 회의 장면
1998년, ISO 작업 그룹은 C++를 ISO/IEC 14882:1998로 처음 표준화했으며, 이는 비공식적으로 C++98로 알려져 있다. 2003년에는 C++98에서 발견된 문제들을 수정한 ISO/IEC 14882:2003이라는 새로운 버전의 C++ 표준을 발표했다.
다음 주요 개정판은 비공식적으로 "C++0x"로 불렸으나, 2011년이 되어서야 발표되었다. C++11 (14882:2011)은 핵심 언어와 표준 라이브러리 모두에 많은 추가 사항을 포함했다.
2014년에는 C++11의 소규모 확장판으로 주로 버그 수정과 작은 개선을 특징으로 하는 C++14 (C++1y로도 알려짐)가 발표되었다. 국제 표준 초안(Draft International Standard) 투표 절차는 2014년 8월 중순에 완료되었다.
C++14 이후, 비공식적으로 C++1z로 알려진 주요 개정판 C++17은 2017년 7월 중순 ISO C++ 위원회에 의해 완성되었으며, 2017년 12월에 승인 및 발표되었다.
C++ 언어에는 두 가지 주요 구성 요소가 있다. 주로 C 서브셋에 의해 제공되는 하드웨어 기능의 직접적인 매핑과, 그러한 매핑을 기반으로 한 오버헤드 없는 추상화이다. 스트롭스트룹은 C++를 "효율적이고 우아한 추상화를 구축하고 사용하기 위해 [설계된] 가벼운 추상화 프로그래밍 언어"라고 설명하며, "하드웨어 접근과 추상화를 모두 제공하는 것이 C++의 기초이다. 이를 효율적으로 수행하는 것이 다른 언어들과 차별화되는 점이다"라고 말한다.
C++ 표준은 핵심 언어와 표준 라이브러리의 두 부분으로 구성된다. C++ 프로그래머는 모든 주요 C++ 구현체에서 표준 라이브러리를 사용할 수 있기를 기대한다. 여기에는 집계 타입(벡터, 연결 리스트, 맵(예: 트리 맵 및 해시 맵), 셋(예: 트리 셋 및 해시 셋), 큐, 스택, 배열, 튜플), 알고리즘(find, for_each, binary_search, random_shuffle 등), 입출력 시설(입출력 스트림, 콘솔 및 파일 읽기/쓰기), 파일 시스템 조작, 지역화 지원, 자동 메모리 관리를 위한 스마트 포인터, 정규 표현식 지원, 멀티스레딩 라이브러리, 원자성(atomics) 지원(외부 동기화 없이 한 번에 최대 하나의 스레드에서 변수를 읽거나 쓸 수 있게 함), 시간 유틸리티(측정, 현재 시간 가져오기 등), C++ 예외 처리를 사용하지 않는 오류 보고를 C++ 예외로 변환하는 시스템, 난수 생성기, 그리고 C++ 타입 시스템을 준수하도록 약간 수정된 C 표준 라이브러리 버전이 포함된다.
C++ 표준 라이브러리의 설계는 C 표준 라이브러리와 마찬가지로 미니멀리즘을 추구하며 프로그래밍을 위한 핵심 기능만을 포함한다. 자바 표준 라이브러리나 C# 표준 라이브러리에서 제공하는 보다 전문적인 기능은 대부분 갖추고 있지 않다. 더 많은 기능이 필요한 경우, 표준 라이브러리를 보완하기 위해 추가 기능을 제공하는 Boost 라이브러리나 POCO C++ 라이브러리와 같은 타사 라이브러리를 사용할 수 있다.
C++ 라이브러리의 큰 부분은 표준 템플릿 라이브러리(STL)를 기반으로 한다. STL이 제공하는 유용한 도구에는 객체 컬렉션인 컨테이너(예: 벡터 및 연결 리스트), 컨테이너에 배열과 유사하게 접근할 수 있게 하는 반복자, 그리고 검색 및 정렬과 같은 작업을 수행하는 알고리즘이 포함된다.
또한, 호환 가능한 인터페이스를 제공하는 (멀티)맵(연관 배열)과 (멀티)셋이 제공된다. 따라서 템플릿을 사용하면 어떠한 컨테이너나 반복자에 의해 정의된 어떠한 시퀀스에 대해서도 작동하는 제네릭 알고리즘을 작성할 수 있다.
C에서와 마찬가지로, 라이브러리의 기능은 #include지시문을 사용하여 표준 헤더를 포함함으로써 접근할 수 있다. C++ 표준 라이브러리는 105개의 표준 헤더를 제공하며, 그중 27개는 권장되지 않는다(deprecated). C++20에서 모듈이 도입됨에 따라 이러한 헤더들은 import로 접근할 수 있게 되었으며, C++23에서는 importstd;를 통해 표준 라이브러리 전체를 모듈로서 직접 임포트할 수 있다. 현재 C++ 표준 라이브러리는 std와 std.compat(C 표준 라이브러리 기능을 전역 이름공간으로 내보내는 std 호환 모듈) 두 가지 모듈을 제공한다.
표준 라이브러리는 수년 동안 제네릭 알고리즘과 컨테이너를 실험해 온 알렉산더 스테파노프가 원래 설계한 STL을 통합하고 있다. 그가 C++를 시작했을 때, 그는 마침내 인라이닝과 함수 포인터 대신 컴파일 타임 바인딩을 사용하는 것과 같은 C++의 기능 덕분에 C 표준 라이브러리의 qsort보다 더 나은 성능을 내는 제네릭 알고리즘(예: STL sort)을 만들 수 있는 언어를 발견했다. 표준에서는 이를 표준 라이브러리의 일부일 뿐이기에 "STL"이라고 부르지 않지만, 이 용어는 표준 라이브러리의 나머지 부분(입출력 스트림, 국제화, 진단, C 라이브러리 서브셋 등)과 구별하기 위해 여전히 널리 사용된다.
대부분의 C++ 컴파일러와 모든 주요 컴파일러는 C++ 표준 라이브러리의 표준 준수 구현체를 제공한다.
C++ Core Guidelines
C++ Core Guidelines는 C++의 창시자 비야네 스트롭스트룹과 C++ ISO 작업 그룹의 의장이자 소집자인 허브 서터(Herb Sutter)가 주도하는 프로젝트이다. 이는 프로그래머들이 C++11 이상의 언어 표준에 대한 모범 사례를 사용하여 '모던 C++'를 작성하도록 돕고, 컴파일러 및 정적 분석 도구 개발자들이 잘못된 프로그래밍 습관을 잡아내는 규칙을 만들 수 있도록 돕는 것을 목표로 한다.
주요 목적은 타입 및 자원 안전성이 보장된 C++를 효율적이고 일관되게 작성하는 것이다.
Core Guidelines는 CPPCon 2015의 기조 연설에서 발표되었다.
지침과 함께 GSL(Guideline Support Library)이 제공되는데, 이는 지침을 구현하기 위한 타입과 함수들로 구성된 헤더 전용 라이브러리이며 지침 규칙을 강제하기 위한 정적 분석 도구와 함께 사용된다.
호환성
컴파일러 벤더들에게 더 큰 자유를 주기 위해 C++ 표준 위원회는 네임 맹글링, 예외 처리 및 기타 구현 관련 기능의 구현 방식을 강제하지 않기로 결정했다. 이 결정의 단점은 서로 다른 컴파일러에 의해 생성된 목적 파일이 서로 호환되지 않을 수 있다는 것이다. 그러나 특정 시스템이나 운영체제를 위한 컴파일러 표준화 시도들이 있다. 예를 들어, Itanium C++ ABI는 (그 이름에도 불구하고) 프로세서 독립적이며 GCC와 Clang에 의해 구현되었다.
C++는 종종 C의 상위 집합으로 간주되지만 이것이 엄밀히 사실인 것은 아니다. 대부분의 C 코드는 C++에서 올바르게 컴파일되도록 쉽게 수정될 수 있지만, 유효한 C 코드가 C++에서 유효하지 않거나 다르게 동작하게 만드는 몇 가지 차이점이 있다. 예를 들어, C는 void*에서 다른 포인터 타입으로의 암시적 변환을 허용하지만 C++는 (타입 안전성 문제로) 이를 허용하지 않는다. 또한 C++는 new 및 class와 같은 많은 새로운 키워드를 정의하는데, 이들은 C 프로그램에서 식별자(예: 변수 이름)로 사용될 수 있다.
어떤 호환성 문제들은 1999년 개정된 C 표준(C99)에서 해결되었는데, 현재 C99는 한 줄 주석(//)이나 코드와 섞인 선언 등 C++ 기능을 지원한다. 반면에 C99는 C++에서 지원하지 않거나 C++에서 중복되거나 호환되지 않는 여러 새로운 기능들을 도입했다. 여기에는 가변길이배열, 네이티브 복소수 타입(C++ 표준 라이브러리의 std::complex 클래스가 유사한 기능을 제공하지만 코드 호환성은 없음), 지정된 초기화(designated initializers), 복합 리터럴, 그리고 restrict 키워드가 포함된다. C99에서 도입된 일부 기능들은 이후 버전인 C++11에 포함되었다(중복되지 않는 기능 위주). 하지만 C++11 표준은 문자열 리터럴을 문자 포인터에 할당하는 것을 금지하는 것과 같은(C에서는 여전히 유효함) 새로운 호환성 문제를 도입하기도 했다.
C와 C++ 코드를 혼용하려면, C와 C++ 양쪽에서 호출되거나 사용될 모든 함수 선언이나 정의를 extern"C"{/*...*/} 블록 안에 두어 C 링키지(linkage)로 선언해야 한다. 그러한 함수는 네임 맹글링에 의존하는 기능(예: 함수 오버로딩)을 사용할 수 없다.
인라인 어셈블리
C 또는 C++로 개발된 프로그램은 성능 최적화가 필수적일 때, 고급 프로그래밍 언어에 비해 저급 기능, 더 빠른 속도, 강화된 제어력을 활용하기 위해 인라인 어셈블리를 사용하기도 한다. C++는 asm 선언을 사용하여 어셈블리어를 내장하는 것을 지원하지만, 인라인 어셈블리의 호환성은 컴파일러와 아키텍처에 따라 크게 달라진다. 파이썬이나 자바와 같은 고급 언어 기능과 달리 어셈블리 코드는 기본 프로세서와 컴파일러 구현에 크게 의존한다.
컴파일러별 차이점
다양한 C++ 컴파일러는 인라인 어셈블리를 서로 다른 방식으로 구현한다.
GCC (GNU 컴파일러 모음) 및 Clang: GCC 확장 인라인 어셈블리 문법을 사용한다. -ansi 및 -std 옵션으로 컴파일할 수 있는 코드를 작성할 때는 asm 대신 __asm__ 키워드를 사용하여 입력/출력 피연산자와 클로버드(clobbered) 레지스터를 지정할 수 있다. 이 방식은 인텔 및 IBM 컴파일러 등에서 널리 채택하고 있다.
MSVC (마이크로소프트 비주얼 C++): 인라인 어셈블러가 컴파일러에 내장되어 있다. 이전에는 __asm 키워드를 통한 인라인 어셈블리를 지원했으나, 64비트 모드에서는 이 지원이 제거되어 대신 별도의 .asm 모듈이 필요하다.
TI ARM Clang 및 임베디드 컴파일러: 텍사스 인스트루먼트의 TI Arm Clang과 같은 일부 임베디드 시스템 컴파일러는 인라인 어셈블리를 허용하지만, 레지스터 규약 및 호출 규약과의 충돌을 피하기 위해 더 엄격한 규칙을 적용한다.
C++와 어셈블리 간의 상호운용성
C++는 ASM 코드를 통합하는 두 가지 기본 방법을 제공한다.
1. 독립 실행형 어셈블리 파일 – 어셈블리 코드를 별도로 작성하고 C++ 코드와 연결한다.
2. 인라인 어셈블리 – 컴파일러 전용 확장 기능을 사용하여 C++ 코드 내에 어셈블리 코드를 내장한다.
↑Stroustrup, Bjarne (2020년 6월 12일). 《Thriving in a crowded and changing world: C++ 2006–2020》. 《Proceedings of the ACM on Programming Languages》4 (Association for Computing Machinery (ACM)). 1–168쪽. doi:10.1145/3386320. ISSN2475-1421. S2CID219603741.
↑Naugler, David (May 2007). 《C# 2.0 for C++ and Java programmer: conference workshop》. 《Journal of Computing Sciences in Colleges》22. Although C# has been strongly influenced by Java it has also been strongly influenced by C++ and is best viewed as a descendant of both C++ and Java.
↑이 코드는 비야네 스트롭스트룹의 정오표 페이지(633쪽)에서 발췌했다. 그는 std::endl보다는 '\n'을 사용할 것을 권장한다. 또한 main 함수에서의 암시적인 return 0;에 대한 설명은 Can I write "void main()"?보관됨 2020-07-02 - 웨이백 머신을 참고하라. 이 암시적인 반환은 다른 함수에서는 사용할 수 없다.