[[컴퓨터공학|컴퓨터 과학 & 공학
Computer Science & Engineering
]]- [ 펼치기 · 접기 ]
- ||<tablebgcolor=#fff,#1c1d1f><tablecolor=#373a3c,#ddd><colbgcolor=#0066DC><colcolor=white> 기반 학문 ||수학(해석학 · 이산수학 · 수리논리학 · 선형대수학 · 미적분학 · 미분방정식 · 대수학(환론 · 범주론) · 정수론) · 이론 컴퓨터 과학 · 암호학 · 전자공학 · 언어학(형태론 · 통사론 · 의미론 · 화용론 · 음운론) · 인지과학 ||
하드웨어 구성 SoC · CPU · GPU(그래픽 카드 · GPGPU) · ROM · RAM · SSD · HDD · 참조: 틀:컴퓨터 부품 기술 기계어 · 어셈블리어 · C/C++ · C# · Java · Python · 바이오스 · 절차적 프로그래밍 · 객체 지향 프로그래밍 · 해킹 · ROT13 · 일회용 비밀번호 · 사물인터넷 · 와이파이 · GPS · 임베디드 · 인공신경망 · OpenGL · EXIF · 마이크로아키텍처 · ACPI · UEFI · NERF · gRPC · 리버스 엔지니어링 · HCI · UI · UX · 대역폭 · DBMS · NoSQL · 해시(SHA · 브루트 포스 · 레인보우 테이블 · salt · 암호화폐) · RSA 암호화 · 하드웨어 가속 연구
및
기타논리 회로(보수기 · 가산기 · 논리 연산 · 불 대수 · 플립플롭) · 정보이론 · 임베디드 시스템 · 운영 체제 · 데이터베이스 · 프로그래밍 언어{컴파일러(어셈블러 · JIT) · 인터프리터 · 유형 이론 · 파싱 · 링커 · 난해한 프로그래밍 언어} · 메타데이터 · 기계학습 · 빅데이터 · 폰노이만 구조 · 양자컴퓨터 · 행위자 모델 · 인코딩(유니코드 · MBCS) · 네트워크 · 컴퓨터 보안 · OCR · 슈퍼컴퓨터 · 튜링 머신 · FPGA · 딥러닝 · 컴퓨터 구조론 · 컴퓨터 비전 · 컴퓨터 그래픽스 · 인공지능 · 시간 복잡도(최적화) · 소프트웨어 개발 방법론 · 디자인 패턴 · 정보처리이론 · 재귀 이론 · 자연어 처리(기계 번역 · 음성인식) · 버전 (버전 관리 시스템 · Git · GitHub)
<colcolor=#00599c,#659AD2> C++ | |
개발 | 비야네 스트로스트룹 |
버전 | 23 |
[clearfix]
1. 개요
“A light-weight abstraction programming language”
“가볍게 추상화한 프로그래밍 언어”
- Bjarne Stroustrup
“가볍게 추상화한 프로그래밍 언어”
- Bjarne Stroustrup
#!syntax cpp
#include <iostream>
int main() {
std::cout << "Hello World!";
return 0;
}
Hello World!
덴마크의 컴퓨터 과학자 비야네 스트로스트룹(Bjarne Stroustrup)[1]가 C언어를 바탕으로 제작했다. 1979년에 C언어에서 직접적으로 파생된 C with Classes라는 이름의 언어로 시작되었다가, 1983년에 지금의 이름을 갖게 되었다. 그리고 객체 지향 및 일반화 프로그래밍과 같은 멀티 패러다임을 지원하는 프로그래밍 언어이다.C언어에서 ++
라는 것은 원래 값에 1을 더해서 대입하라는 뜻이다.[2] C는 B 언어를 계승한다는 의미에서 C가 되었는데 왜 D가 아니라 C++가 되었냐 하면, C 언어를 거의 그대로 두고 필요한 만큼만 향상시켰기 때문이라고 한다. 비슷한 이름인 C#과의 차이도 이러한 점에서 나타난다.쓸 때는 C++라고 쓰지만 읽을 때는 시 플러스 플러스, 혹은 줄여서 시플플이라고 읽는다. 한국에서는 사실상 속어에 가까운 씨쁠쁠로 불린다. '씨뿔뿔'로 발음되는 경우도 많다. 교수들이나 풀네임으로 ‘씨 플러스 플러스’라고 읽는 정도. 나이가 꽤 있는 교수 중에는 간혹 '시 더블 플러스'라고 읽는 경우도 있다. 미국에서는 그냥 씨 플러스 플러스 또는 확장자 명인 CPP(시피피)라고 읽는다.한국에서 컴퓨터공학과를 다닐 경우 배울 수 있는 프로그래밍 언어 3개 중에 속한다. 나머지 둘은 C와 Java.[3] 학교마다 다르지만 1학년때 아예 다른 C, Python을 배우고 2학년 1학기때 Java, 2학기때 C++ 과목을 수강하는 곳도 있다. 예시로 서울대학교의 경우에는 1학년 1학기에 Python으로 코딩을 입문하고, 1학년 2학기에 C언어로 어느 정도 큰 프로젝트를 짜 보고, 2학년 1학기에 C++과 Java를 배우면서 객체 지향 프로그래밍을 배우게 된다.
온라인 상으로 코드를 실행시켜 보고 싶다면 여기로.
C++의 창시자는 C++가 단순한 객체 지향 프로그래밍 언어가 아니라 멀티 패러다임 언어라고 강조한다. # C++는 프로그래머의 자유도가 높은 언어로써, 객체 지향이나 절차 지향 등의 설계에 제한을 두지 않는다. C++에서는 객체 지향 프로그래밍 패러다임과 동등한 강도로 일반화 프로그래밍 패러다임을 강조하고 있다. 스트로우스트루프의 책 The C++ Programming Language 4판을 참고하면 "3부 추상화 메커니즘" 단원의 절반(7개 섹션)은 객체 지향, 나머지 절반(7개 섹션)은 일반화 프로그래밍에 할애하고 있다. 그리고 "4부 표준 라이브러리" 단원의 1/3이 STL이고, 2/3는 나머지 표준 라이브러리를 설명하고 있다. 쉽게 말하자면 C++는 기존의 C 문법이 대표하는 절차적 프로그래밍, 클래스가 대표하는 객체 지향 프로그래밍, 템플릿이 대표하는 일반화 프로그래밍의 세 기둥으로 지지되고 있는 언어이다. 유사한 의견으로 Effective C++의 저자 스콧 마이어스는 C++가 4가지 하위언어의 연합체라고 언급한다. C, 객체 지향 C++, 템플릿 C++, STL.[4]
1.1. C와의 차이점
초기 C++가 C언어를 기반으로 시작했기 때문에 지금도 대부분의 C 프로그램은 C++ 컴파일러에서도 문제없이 컴파일된다. 초기 C++ 컴파일러는 일단 C++ 코드를 C로 변환하고 그걸 C로 재컴파일하는 방식을 사용했을 정도. 다만, C가 항상 C++의 부분집합이었던 것은 아니라 지금도 구조체같이 몇몇 부분에서 차이점이 있다. "잘 짜인 C 프로그램은 C++ 컴파일러로 컴파일할 수 있어야 한다"는 말도 1999년에 C99 표준이 나오면서 틀린 말이 되었다. 순수 C 소스 코드를 C++로 컴파일 할 때 문제의 여지가 생길 가능성이 있다.그러나 C++는 C와 프로그래밍 패러다임이 크게 다르다. C는 태초부터 절차 지향으로 설계된 운영체제를 만들기 위한 언어였으며, 지금도 메모리와 각종 저수준(low level) 프로그래밍을 위한 언어이기 때문이다[5]. 반면 C++는 절차 지향, 객체 지향, 일반화 프로그래밍, 함수형 프로그래밍을 모두 지원하는 언어다. 그래서 C로 작성된 프로그램에서 C++ 방식으로 코딩하려면 해당 코드에서 C++에 새로 도입된 것을 추가하는 게 아니라, 설계부터 시작해서 완전히 새로 해야 하는 경우가 많다. 곧 C를 알고 있다고 C++를 쉽게 할 수 있는 것은 아니다. 세간에서 C, C++ 중 어디가 쉽다라던가 하는 건 어디까지나 간단한 프로그램의 예일 뿐이다. 또한 C++의 객체 지향이 다른 객체 지향 언어에 비해 이해하기가 만만한 개념이 아닌 데다가 C++의 객체 지향은 C언어를 기저에 유지하면서 여러 구성 요소를 추가했기 때문에 신경 써야 할 부분이 많다. 그래서 다른 객체 지향 언어에서보다 잘 다루는데 더 많은 공부가 필요하다. C++을 잘 활용하려면 자료구조 및 알고리즘, 입출력 스트림, 그리고 적어도 다른 언어에서 일반화 프로그래밍이 쓰이는 것처럼 템플릿을 활용할 수는 있어야 한다. 그래서 C언어를 알고 있는 사람이 C++ 초보자용 교재를 1권 끝내고 프로그램을 만들어 보라고 해도, 대부분 C++의 입출력 객체를 이용하는 정도를 넘지 못하고 절차적 프로그래밍을 그대로 따라가는 영락없는 C 방식에서 벗어나지 못한다.
C++에서 C 전향도 만만치가 않다. 절차지향 언어의 사고방식이 머릿속에 굳어버려 코드를 전환하는 데 방해가 된다. C++가 C의 모든 기능을 포괄하고 있으므로 C++를 할 줄 알면 C도 할 줄 안다고 생각하기 쉽지만, 사실 C++가 명시적으로 비교적 간단히 사용할 수 있도록 제공하는 기능들을 C에서는 암묵적으로 여러 가지 수많은 '트릭'을 통해서 쥐어짜내듯이 만들어 사용하는 경우가 많다. 지금도 많은 대학에서 컴공 1학년 1학기 때 C를 먼저 가르치고 빠르면 2학기, 늦어도 2학년에 C++를 가르치지만, 반면에 교수가 절차 지향이 머리에 굳어버린다며 C++와 객체를 먼저 가르치고 C는 아예 건드리지도 않고 다른 하드웨어 관련 학과에서만 가르치는 대학들도 많다.
따라서, 초심자 입장에서는 C와 C++는 완전히 다른 언어로 파악하고 접근해야 한다.
#!syntax cpp
struct A { int x, y; };
struct B { struct A a; };
struct A a = {.y = 1, .x = 2}; // valid C, invalid C++ (out of order)
int arr[3] = {[1] = 5}; // valid C, invalid C++ (array)
struct B b = {.a.x = 0}; // valid C, invalid C++ (nested)
struct A a = {.x = 1, 2}; // valid C, invalid C++ (mixed)
[6]그외에
_Generic(type)
을 사용한 자료형에 대해 안전한 매크로의 지원 등 C에서만 지원되는 문법이 몇몇 있다.- 클래스 비교 코드
#!syntax cpp // C 스타일 typedef struct GameObjectTag { long id; float x, y, z; } GameObject; static GameObject* CreateObject() { static long __gobject_id = 1; GameObject* result = (GameObject*) malloc(sizeof GameObject); if (result) { result->id = __gobject_id++; } return result; } static void InitObject(GameObject* obj, long id) { obj->id = id; obj->x = 0; obj->y = 0; obj->z = 0; } static void InitObject(GameObject* obj, long id, float x, float y, float z) { obj->id = id; obj->x = x; obj->y = y; obj->z = z; } static void MoveObject(GameObject* obj, float x, float y, float z) { obj->x = x; obj->y = y; obj->z = z; } #include <iostream> struct Foo { int n ; Foo ( ) { std :: cout << "statikus konstruktor \n " ; } ~Foo ( ) { std :: cout << "statikus destruktor \n " ; } } ; Foo f ; // statikus objektum int main ( ) { std :: cout << "főfüggvény \n " ; } // C++ 스타일 class GameObject { public: constexpr GameObject(const long& new_id, const float& cx = 0, const float& cy = 0, const float& cz = 0) noexcept : id(new_id), x(cx), y(cy), z(cz) {} constexpr void Move(const float& x= 0, const float& y = 0, const float& z = 0) noexcept { this->x = x; this->y = y; this->z = z; } [[nodiscard]] constexpr std::tuple<float&, float&, float&> GetPosition() noexcept { return std::tie(x, y, z); } [[nodiscard]] constexpr std::tuple<const float&, const float&, const float&> GetPosition() const noexcept { return std::tie(x, y, z); } long myID = -1; // 기본값 float x, y, z; }
this
를 활용하면 인자 전달 없이 클래스에 속한 메서드 호출만 할 수 있다. 그외에 기본 연산자 오버로딩, friend
를 통해 외부 클래스 또는 함수와 속성 공유를 할 수 있다.#!syntax cpp
std::ios_base::sync_with_stdio(false);
iostream
이나 fstream
등 입출력 스트림이 C의 입출력 함수보다 상당히 느리다. C++의 입출력 스트림은 예외없는 입출력을 위해 try
문은 물론 온갖 내부 비트 플래그가 돌아가고 있기 때문이다. 만약 프로그램내에서 std::cin
, std::cout
등 C++ 스트림[iostream] 계열만 사용하고 stdin
, stdout
등 표준 C 스트림[stdio.h]을 사용하지 않는다면, 각 입출력 스트림간의 동기화를 정지시켜 iostream에 비약적인 속도 향상을 가져올 수 있다 [9].1.2. 객체 지향 프로그래밍
C++는 객체 지향 프로그래밍을 지원하지만, C++의 객체 지향은 다른 객체 지향 언어에서와는 성격이 좀 다르다. 대다수의 객체 지향 언어에서는 많은 부분을 런타임에 처리하며 메모리를 자동으로 관리해준다. C++은 기반 프레임워크가 존재하지 않아 클래스가 어떤 일급 객체가 아니라, 일반 변수처럼 메모리 덩어리일 뿐이다. 최대한 많은 것을 컴파일 타임에 처리하는 것을 지향하고 동적인 메모리 할당을 지양한다. 그리고 결정적으로 메모리 등을 프로그래머가 직접 관리하게 하기 때문에 클래스를 포함해 전반적인 프로그램 설계 자체가 상당한 차이를 보이게 된다.Java 등의 다른 객체 지향 언어에서와 같은 방식으로 C++ 클래스를 디자인하면 거의 틀림없이 런타임 오류 또는 메모리 문제가 발생한다. 특히 쓰레기 수집을 지원하는 Java로 입문하여 C++로 갈아타는 테크를 탄 학생이라면 처음에는 메모리가 줄줄 새는 프로그램을 만들게 될 것이다. 반면 C++ 스타일을 숙지하고 다른 객체 지향 언어에서 프로그래밍을 하는 경우 특별히 안 될 것은 없지만, 해당 언어의 원어민 스타일로 작성한 코드에 비해 시간이 많이 걸리고 클래스 및 프로그램 구조가 지나치게 경직되는 경향이 있다. 소멸자가 호출되지 않는 등의 차이점은 있지만 심각한 문제가 되는 경우는 많지 않다.
이러한 차이가 생기는 것은 대부분의 객체 지향 언어는 직접적으로 Smalltalk의 영향을 받은 반면, C++는 Smalltalk보다 먼저 객체 지향의 초보적인 개념을 제시한 시뮬레이션 전용 언어인 Simula에서 직접 영향을 받았기 때문이다. [10] 이는 C 프로그램과의 호환성을 고려한 결과이기도 하지만, 기본적으로 C++에서 프로그램의 성능을 희생시키지 않기 위해서였다. Smalltalk의 경우 당시의 기술적 한계도 있고 해서 C보다 대체로 수십 배 정도 느렸고, 이는 당시 C++에서 지향하는 결과가 아니었기 때문이다. 이런 차이 때문에 Java, C# 등의 언어를 먼저 접한 프로그래머들은 C++의 객체지향이 짝퉁이라며 싫어하기도 한다. 하지만 순수 객체 지향 프로그래밍 언어임을 전면에 내세우는 Java나 C#과 달리, 객체지향 패러다임도 지원하는 다중 패러다임 언어인 C++ 입장에서는 얼마나 순수하게 객체 지향의 이상을 잘 따르는가보다, C++가 제공하는 온갖 패러다임까지 아우르는 내적 일관성이 더 중요하므로 해당 언어들과 C++를 동일선상에 놓고 비교할 수는 없다.
대표적인 예시로 인자로 전달하는 값은 기본적으로 복사되는 것, 함수 내부에서 객체를 동적 할당하고 주소를 반환하는 것이 있다. 이는 C++에선 메모리 문제를 일으키기 쉬운 방식이라서 설계 단계부터 이런 동작을 배제해야할 필요가 있다. 거의 대부분의 프로그램은 실행되고 있는 현재 문맥에서의 지역 변수를 스택 영역에 저장하는데, 한 문맥의 실행이 완료되면 그 함수의 스택 영역 변수를 위한 메모리는 모두 삭제된다. 그리고 이 변수는 쓰레기 데이터로 남아있다가 다른 함수를 호출할 때 덮어씌워진다. 공유 자원과 같은 특정 데이터를 유지하려면 힙 영역에 할당해야 한다. 가비지 컬렉션이 자동으로 되는 언어에서는 언어 설계 차원에서 메모리에 대한 걱정을 덜기 위해 사용되지 않는 메모리를 자동으로 해제 해주기 때문에 매우 흔히 사용되는 방법이다. [11]
그러나 문제가 생기는 건 오래된 스타일의 C++ 코드에서나 그런 것이고, Modern C++에서는 스마트 포인터를 사용하거나 이를 이동 연산[12]을 통해 그들과 완전히 같은 구조를 구현 가능하기 때문에 더 이상 해당이 없는 사항이다. 예를 들어 한 동적 객체를 여러 소유권자가 공유하는 경우 (참조 대상에 대한 횟수를 기록하는) 레퍼런스 카운팅을 지원하는
std::shared_ptr
를, 단일 소유자만 존재하는 경우 std::unique_ptr
를 사용한다 [13].1.3. 일반화 프로그래밍
C++에서는 템플릿을 이용한 일반화 프로그래밍(Generic Programming)이 매우 폭넓게 사용된다. 특히 C++11을 시작으로 하는 모던 C++는 일반화 프로그래밍을 빼고 이야기하는 것이 불가능하다. 당장 매우 널리 사용되는 문자열 클래스std::string
만해도 실제로 들여다보면 std::basic_string<char, std::char_traits<char>>
와 같은 형태의 클래스 템플릿의 특수화에 지나지 않는다.일반화 프로그래밍의 결과물으로는 C++ 표준 라이브러리의 일부분으로 포함된 컨테이너, STL 같은 것들이 있으므로, C++ 표준 라이브러리를 사용하는 순간 일반화 프로그래밍의 도움을 받는 것이다. 따라서 '나는 C++를 사용하지만 템플릿을 이용한 일반화 프로그래밍은 어려우니까 패스하겠다'는 말은 애초에 성립하지 않는다. 또 다른 예시로, C와는 달리 배열 생성에 포인터 혹은 []을 사용하는 배열 대신에
std::vector
를 기본으로 사용하라고 가르치는데, 이 std::vector
또한 저장될 원소의 자료형을 std::vector<int>
와 같이 템플릿 매개변수로 받아들이는 템플릿 클래스다. 중급 이하 개발자는 라이브러리를 그냥 가져다 쓰면 되고, 직접 만들어 쓸 필요는 없다. 이는 중급 개발자 정도로는 템플릿을 사용한 일반화 프로그래밍 기법을 정확하게 적용하는 것이 무척 까다롭고, 디버깅할 때 이해 불가능한 컴파일러 메세지를 받게 되는 경우가 많아 오류를 수정하기도 어렵기 때문이다. 현재는 C++20에서 concept
의 등장으로 이전보다 상대적으로 알아보기 쉬운 템플릿 작성이 가능해졌고, 컴파일 오류 메세지또한 좀 더 이해하기 쉽고 간결하게 표시되게 되었다.이런 이유로 C++ 학습 초반에 템플릿 프로그래밍을 직접 하는 것을 피하고 기껏해야 컨테이너 클래스만 사용하는 습관이 들다 보니, C++는 단순히 객체 지향 언어이고 STL이라는 템플릿 라이브러리를 덤으로 쓸 수 있는 정도라는 오해가 널리 퍼진 것이라 생각된다. 하지만, 특수 목적의 컨테이너를 설계하거나 범용 라이브러리를 설계하는 수준의 고급 개발자가 되려면 템플릿을 사용한 일반화 프로그래밍을 해야 한다.
Java나 C#에서 찾아볼 수 있는 Generics가 지금 설명한 C++ 일반화 프로그래밍의 아주 제한된 형태의 적용례에 해당한다.
1.4. 메타 프로그래밍
TMP (Template Meta Programming). 템플릿을 사용한 메타 프로그래밍 Wikipedia
C++에서는 템플릿을 사용해 메타 프로그래밍을 할 수 있다. 여기서 메타란 Meta Data (서술 자료)를 의미한다. 값 뿐만 아니라 프로그램, 바이너리, 속성 그 자체도 데이터로 취급한다. 가령 Python의 메타 클래스는 '클래스'를 생성하며 [14] 클래스의 바이트 크기, 필드, 메서드 등을 정의한다. 또한 Python, C#, Swift 등 많은 언어가 int
, double
같은 원시 자료형도 클래스로 보여준다. 하지만 C++은 그럴 수가 없다. C++의 클래스는 메모리 덩어리고, int
라는 단어 자체에는 그저 컴파일러가 int
를 메타 정보로 가진 객체는 32비트 크기로 읽겠다, 말고는 아무 의미도 없다. 다른 언어는 '정보[15]의 메타 정보[16]의 메타 정보[17]를 언어 자체적으로 가져오고, 심지어 정의할 수도 있다. C#, JavaScript, Python이 대표적인 예시다. 반면 C++에선 클래스가 그냥 메모리 덩어리고 메서드도 그냥 쓰기 좋게 만든 함수 포인터다. 전처리기, 컴파일러 확장, 미리 쓰여진 코드에 의존할 뿐 자료형 자체에 대해서는 아무것도 알 수 없다. sizeof
, alignof
, alignas
키워드가 있지만 부족하다. 그리고 직접 클래스 자체의 속성을 정의하려면 using
, static
변수를 사용해 일일히 모든 클래스에 메타 정보를 기입해야 한다. 이 방법은 임의의 클래스, 그리고 원시 자료형에는 적용할 수 없는 문제가 있다. 이 간극을 메우기 위해 대신 템플릿을 사용해 메타 프로그래밍을 시도하는 것이다. 같은 템플릿 문법을 사용하지만 앞 문단의 일반화 프로그래밍과는 엄연히 목표가 다르다. 일반화 프로그래밍이 자료형을 드러내어 컴파일 시기에든 실행 시기에든 코드 확장 및 범용성 증대를 목표로 한다면, 메타 프로그래밍은 명시해야할 자료형을 숨기고, 어떤 자료형에 대해 그 자료형에 대한 정보를 기술하는 것을 목표로 한다. 이는 일반화 프로그래밍과는 다르게 확장이 아니고 특정 자료형에만 코드를 생성하도록 만든다.
- SFINAE(Substitution Failure Is Not An Error): 함수를 오버로딩 하는데 있어 조건에 따라 일부러 오류가 발생하는 템플릿의 구현 코드를 발생시켜 틀리지 않은 특정 구현만 선택되게 만드는 테크닉이다. C++의 템플릿은 자료형의 상태를 서술하기 위해 분명히 존재하지만, 실제로 인스턴스화되는 시점은 런타임 직전 사용자의 코드에서 실제 자료형을 가져와야 한다. C++ 문법의 틈새에 존재하는 문법 오류이지만 런타임 오류가 아닌 상황을 적극 활용하는 것이다. 직역하면 '대입 실패는 오류가 아니다'라는 뜻이다.
그렇다면 C++에서 그냥 메타 프로그래밍이라고 안하고 굳이 앞에 템플릿이라고 붙인 이유가 있을까? C++의 템플릿은 독특한 특성을 많이 가지고 있다. 템플릿 매개변수는 반드시 컴파일 시점에 결정된다. 템플릿 매개변수는 자료형 뿐만 아니라 값도 전달할 수 있다. 템플릿의 실제 코드는 늦게 평가된다. 템플릿은 분명 존재하는 C++ 코드이지만, 실질적으로 전처리기 구문과 다름이 없다. 실행 시점에는 이미 바이너리로 모든 경우에 대해 완성된 상태가 되므로 컴파일 이후에 실행 시간에는 아무 영향이 없다 [18]. 컴파일러가 예측할 수 없는[19] 네트워크 접근, 다중 스레드 작업, 그리고 운영제체 호출을 제외하면 모두 상수 시간에 결정할 수 있다. 곧 C++의 메타 프로그래밍은 자료형의 상태를 기술하는 것에 더해서, 할 수 있는 작업은 컴파일러를 고문해 모조리 미리 처리하는 것이 지상과제가 된다. 이는 C++의 템플릿 문법이 컴파일 시간에 Turing complete하기 때문에 이런 일이 가능한 것이다. C++ 안에 컴파일러 전용의 또 다른 언어가 숨어있는 것과 같은 상황이다. 다른 언어에서는 비슷한 것도 찾기 힘들다.
* Expression Templates: 디자인 패턴의 일종인 Proxy pattern 기반의 Lazy evaluation이 적용되는 효율적인 계산 코드를 컴파일 시점에 생성하는 기법이다. 일반적으로 연산 도중의 임시 객체 생성 문제를 이 기법을 통해 해결하는 경우가 있다. RVO(Return Value Optimization)를 감안하더라도 C++ 특성상 연산자를 활용하는 과정에서, 직접적인 연산을 시도하면 임시 객체의 생성을 완전히 막을 수는 없기 때문이다.
배우기 어렵고 알아보기도 힘들고, 실행 성능을 포기하지 않는 대신 컴파일 시간을 심각하게 포기했다. 심지어 디버깅도 힘들다. 다만 디버그 문제는 자기가 원하는 템플릿에 맞춰 중단점을 거는 게 가능해지는 등 많이 개선된 편이다. 당연히 템플릿에 대하여 깊은 이해가 없다면 아예 이해할 수가 없는 개념이기도 하다. 그래도 알아두면 은근 써먹을 데가 많다. C++에서는 단순히 특정 자료형의 속성 선언부터 함자 클래스[20]를 이용한 방문자 패턴, 트레잇, 타입 리스트, CRTP, mixin 등 수많은 고성능 디자인 패턴은 C++에서는 TMP의 도움 없이는 시도조차 할 수 없다. C++17 기준으로 쓰여진 C++ 템플릿 기본서 는 그 쪽수가 800쪽을 넘는다.
예를 들어, 피보나치 수열을 계산하는 코드는 다음과 같이 쓸 수 있다.
#!syntax cpp
constexpr size_t fibonacci(size_t n) noexcept
{
return (n < 2) ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
constexpr size_t result = fibonacci(7); // 13
아래는 템플릿을 활용해 컴파일 시점에 계산하는 코드이다. [21]
- 템플릿 코드
#!syntax cpp template <size_t N> struct Fibonacci { static constexpr size_t Value = Fibonacci<N - 1>::Value + Fibonacci<N - 2>::Value; }; template<> struct Fibonacci<0> { static constexpr size_t Value = 0; }; template<> struct Fibonacci<1> { static constexpr size_t Value = 1; }; int arr[Fibonacci<7>::Value];
C++17의if constepxr
또는 C++20의consteval
을 활용하면 더 간결하게 쓸 수 있다.#!syntax cpp template<size_t N> constexpr size_t Fibonacci() noexcept // C++20 이후에는 consteval로 지정해도 문제없다. { if constexpr (N < 2) return N; else return Fibonacci<N - 1>() + Fibonacci<N - 2>(); } int arr[Fibonacci<7>()];
그리고 실무에서 가장 많이 쓰이는 테크닉 중 하나로 CRTP (Curiously Recursive Template Pattern) 패턴이 있다. 추상 클래스를 구현할 시 가상 함수 호출에 따른 오버헤드를 막고자 고안되었다. 이는 다음과 같이 작성한다.
- CRTP 예제 코드
#!syntax cpp template <typename Derived> class Base { constexpr void Function() noexcept(noexcept(Cast()->Function())) { Cast()->Function(); } protected: constexpr Derived* Cast() noexcept { return static_cast<Derived*>(this); } constexpr const Derived* Cast() const noexcept { return static_cast<const Derived*>(this); } }; class CRTPDerived1 : public Base<CRTPDerived1> { public: void Function() noexcept // Base::Function은 상수식이 아니고 noexcept(true) { std::print("CRTPDerived1"); } }; template <typename... Ts> class CRTPDerived2 : public Base<CRTPDerived2<Ts...>> { public: constexpr void Function() // Base::Function은 상수식이지만 noexcept(false) { throw "CRTPDerived2"; } };
1.5. 용도
본래 C는 유닉스라는 OS를 만들기 위해 어셈블리 대체용으로 만들어진 언어라, 머신 컨트롤의 저수준 작업이 주된 임무 중 하나였다. C++은 그 이름에서 보이듯이 사실상 C를 대체하기 위한 언어였기 때문에 여러 가지 고수준의 추상 기능들을 집어넣어 추상적인 시스템 위에서만 노는 게 아니라, 저수준의 기계 제어까지 가능한 추상화라는 요상한 철학을 지지한다. 뭔가 딜레마 같지만 C++과 비슷한 정도의 고수준 기능을 제공하는 언어는 절대로 C++만큼 복잡하지 않다. 여타 언어들이 객체 지향 프로그래밍을 구현하면서 동적 바인딩(C++의 가상 함수)을 디폴트로 쓰고 쓰레기 수집을 지원할 때 C++은 정적 바인딩을 디폴트로 하고 수동 메모리 관리를 유지한 것이다. 일반적으로 추상화 수준이 높은 언어일수록 프로그래머 머리로 해야할 구체적인 것들을 컴퓨터가 대신 해주고, 이것이 항상 최적화된 방식은 아니기 때문에 프로그램의 실행 속도가 상대적으로 느리게 마련이지만, C++ 프로그램은 위와 같은 이유로 성능 하락이 거의 없다.C++과 비슷한 정도의 기능을 가진 언어 중에서 C++만큼 빠른 실행 성능을 내는 언어 구현은 흔치 않다. 대신 프로그래머가 언어의 이상한 부분까지 신경쓰지 않으면 안 되는 디자인이 되어 제대로 쓰는 게 굉장히 어려운 언어가 되고 말았다. 추상화의 가장 큰 이유와 장점은 그것을 추상화시킴으로서 그 아래 감춰진 디테일한 부분을 신경쓸 필요가 없게 만드는 것이다. 따라서 저수준 제어와 고수준 추상화의 두 가지 개념은 서로 완전히 충돌하는 부분이다. C++는 저수준 제어를 포기하지 않았기 때문에 프로그래머는 C++로 저수준 작업을 할 때는 디테일한 부분까지 신경써야만 한다. 반대로 C++에서 고수준 기능을 사용하려면 프로그래머가 저런 부분을 감안하여 C++ 방식으로 변형되어 적용된 코딩 문화를 알고 있어야 한다.
애초에 C 언어의 기능을 모두 포함했던 이유는 생산성과 함께 C를 대체하겠다는 두마리의 토끼가 목적이었기 때문이다. 그러나, OS를 만드는 유닉스 커뮤니티들이 C++로의 전환을 거부해서 한마리 토끼는 놓쳤지만 그럼에도 Java라는 강력한 언어가 등장하기 전까지는 C에 비해 압도적인 생산성으로 어플리케이션 소프트웨어 쪽에서 순식간에 대세언어가 되었으나 Java의 등장과 각종 스크립트 언어들의 부상, 그리고 비주얼 베이직에서 Python으로 이어지는 하이퍼 고 생산성 언어들의 등쌀에 현재는 포지션이 좀 애매해진 경향이 있다. 애초에 C의 기능을 전부 포함했던게 공짜로 된 것이 아니라 그만큼 복잡해지고, 컴파일 속도까지 희생하는 역효과도 포함하고 있었고, 덕분에 Java나 C# 등의 기타 고생산성 언어들에 비해 생산성은 떨어지면서 정작 노리고 있던 C의 대체도 날아간 상황.
현재는 클라이언트 쪽에서는 성능이 엄청나게 중요하면서 동시에 개발속도도 크리티컬한 게임[22], 포토샵, 웹 브라우저 등의 데스크탑 어플리케이션, 업무 연속성이 중요한 금융권 IT망 및 금융공학에서 주로 사용된다. 사실 그 외에도 퍼포먼스를 중시하는 경우 여전히 많이 사용된다. 구글에서도 상당히 많이 사용하는 언어이다.# 이미 구글에서 2009년에 개발한 컴파일 기반 언어인 Go가 나와 있었는데도 텐서플로가 C++로 개발되었다는 점이 하나의 예시이다.
2010년대에 이르러서는 CUDA의 강력한 존재 덕분에 인공지능 관련 수요가 급격하게 늘어났다.
2. 문법
자세한 내용은 C++/문법 문서 참고하십시오.3. 언어 명세
자세한 내용은 C++/명세 문서 참고하십시오.4. 표준 라이브러리
자세한 내용은 C++/표준 라이브러리 문서 참고하십시오.|C++ 표준 라이브러리|<table width=90%><tablealign=center><tablebordercolor=#030303,#eeeeee><nopad>
||<:><width=23%>분류||<-2>이름||
||5. 역사
자세한 내용은 C++/역사 문서 참고하십시오.6. 평가
자세한 내용은 C++/평가 문서 참고하십시오.7. 학습 자료
학습 로드맵 겸 영어 학습 자료보통 기능이 적고 사용 분야가 한정된 언어들과 달리, C++는 기능이 매우 방대하기 때문에 온갖 분야에 다 사용되지만[23] 반대급부로 전문가들도 모든 기능을 능숙하게 쓰는 경우가 거의 없고, 자신이 주로 사용하는 분야에서 쓰는 기능만 파는 경우가 많다. 분야마다 주로, 자주 사용하는 기능이 천차만별이다보니 중상급 이상의 레벨에서는 목적지가 크게 갈린다. 때문에 어디에서 시작할 것인가가 꽤나 학습 방향에 중요하게 작용해서 입문 및 초급자용 도서 추천이 매우 곤란한 편에 속한다.
추가적으로 몇 년도 C++ 버전을 기준으로 썼는지도 고려해야 한다. 역사가 길며 지속적으로 갱신되었다는 특성 때문에 일부 분야에서는 격변 수준으로 바뀐 영역도 많으며, 최신 기능들이 추가되기 전에 저술되었던 예전의 명저들이 현 시대상에는 맞지 않는 경우도 많다. 물론 유명한 서적들의 경우 최신 기능도 포함한 개정판이 나오는 경우가 있지만, 예전 내용 그대로에 최신 기능을 겉핥기 수준으로 덧붙인 수준에 불과한 경우도 많아 잘 찾아보아야 한다.
또한 공학 서적이 그렇듯 컴퓨터 공학자들 대부분이 외국인이기 때문에 필독서라고 할만한 책은 대부분 외국 원서를 번역한 번역서인데, 번역에 있어 전문지식이 반드시 필요한 공학 서적이라는 특징이 번역자들 수준이 크게 떨어지는 국내 출판업계의 특성과 겹쳐 상당 수의 번역서들이 절망적인 수준의 번역을 자랑한다. 웬만한 외국 번역서적들 태반에 번역 문제를 지적하는 후기들이 있을 정도며 상당한 수의 서적에서 오탈자 검수가 제대로 되지 않는 경우가 태반이다. 크게는 치명적인 오역으로 내용을 정 반대로 이해하게 만들거나, 이러한 심각한 수준은 아니더라도 일부는 컴퓨터 공학에 대한 지식이 전무한 비전공자가 번역하거나 해서 생소한 번역어를 사용하거나 하는 경우가 있다. 이런 문제가 없더라도 원서에서 쉽게 서술된 내용이 직역을 거쳐 이해하기 어려운 딱딱한 문장으로 둔갑하는 경우도 많다.
게다가 애시당초에 번역을 하면 안되는 멀쩡한 코드 예제까지도 편집 과정에서 잘못 건드리는 경우도 있어, 예제 그대로 타이핑해서 실행해도 컴파일 에러를 뿜어내는 경우도 있다. 이런 문제의 경우 사실 어느정도 문법에 익숙하다면 금방 해결 가능한 사소한 수준의 문제라 뇌내보완이 가능하나, 문제는 이런 기초 입문서를 배우는 초심자로써는 사소한 오탈자로 인한 에러도 잡아내기 어렵다는 것이다.
때문에 능력이 되면 원서를 읽는 것이 낫다. 하지만 공학 분야의 특성상 매우 훌륭하게 번역되거나 아예 한국인 저자가 쉽게 풀어쓴 내용으로도 이해하기 어려운 지식을 영어 원문을 보고 이해하려면 원어민급 독해력이 있어도 어려운 일이기 때문에 차선책으로 그나마 잘 번역된 책을 찾거나, 아니면 아예 한국인 저자가 한국어 기반으로 쓴 책을 먼저 보고, 영어 실력을 좀 쌓은 이후에 아예 원서로 넘어가는 식으로 공부하는 것을 추천한다.
아래의 도서들은 한국어 번역본이 존재하는 도서를 우선시했다.
<colbgcolor=#fff><colcolor=#000> 입문 & 초급 | 입문용 서적으로는 외국의 입문서라고 하면 Teach Yourself 시리즈나, Primer 시리즈 등이 가장 처음 볼 책으로 추천되곤 한다. 다만 C++의 분야가 원체 방대한데다 보통 초심자용 책은 상세히 풀어쓰는 경향 때문에 분량이 늘어나는 특성이 있기 때문에 둘 다 엄청나게 두꺼운 편이며, 예제나 서술 방식에 호불호가 크게 갈리는 책이다. 한국인 저자의 책이라면 대학교재로 많이 쓰이는 명품 C++ programming 책이 있다. |
C++ 창시자인 비아네 스트로스트룹 본인이 학부생 수업 교재로 사용할 목적으로 쓴 Programming: Principles and Practice using C++는 보통 컴퓨터 관련 학부 2학년에 존재하는 프로그래밍 방법론 등의 이름을 가진 특정 언어와는 무관한 수업의 교재이지만, C++ 입문서로도 꽤 유용하다. | |
오래된(2005년) 책이지만 Effective C++(3판)을 보는 것도 좋다. 번역이 매끄러워 읽기 좋고 이해하기 쉽다. 이 책은 입문용 책이 아니라 기초를 모두 알고 있는 사람이 읽으면 좋은 책으로 C++의 기초를 이해하고 있다면 C++의 STL 에 대한 책을 같이 병행하는 것이 좋다. 한국인 저자의 책이라면 뇌를 자극하는 C++ STL이 있다. | |
한국인 저자가 쓴 책으로 두들낙서의 C/C++ 한꺼번에 배우기가 있다. 저자의 유튜브 채널에서 동영상 강의를 무료로 볼 수 있다. | |
인터넷으로 배우고 싶다면 모두의 코드를 추천한다. 위키독스에서 C++ 이야기(A Story of C++)를 볼 수도 있다. 영어에 능숙하다면 LearnC++도 좋은 선택이다. | |
대부분의 C++ 책들이 C언어를 배웠다는 전제로 쓰여있는데, C언어를 안 하고 바로 C++를 하고 싶다면 그림으로 배우는 C++ Programming 2nd Edition 이 책을 보면 된다. | |
C언어 없이 C++를 바로 시작하고 싶고 상세한 설명을 원한다면 포르잔 C++ 바이블을 읽는 것이 좋다. 파이썬 교재로 유명한 혼자 공부하는 파이썬의 저자가 번역한 책이라 번역의 질이 보장이 된다는 게 장점이다. 다만 대학 교재용으로 나왔다보니 연습 문제의 해답이 제공되지 않는다는 단점이 있지만[24] 구글에 검색을 해보면 블로그에 개발자들이 올려놓은 해답을 찾을 수 있다. 1000페이지가 넘어가는 두께에 질렸다면 축약본인 포르잔 C++ 에센셜도 있는데 이 책의 역자는 자신의 유튜브 영상 댓글에서 혼자 공부하는 사람은 바이블을 읽을 것을 권장했다. | |
C 초급용 추천서적 5종, C++ 초급용 추천서적 5종 | |
중급 | 일단 초급용 서적을 한 권 독파하고 나면, Effective Modern C++, C++ Template: The Complete Guide, C++ Concurrency in Action 정도의 책을 권하는 사람이 많다. 특히 스콧 마이어스의 Effective Modern C++는 거의 필독서에 가깝다.[25] |
C언어의 창시자가 쓴 The C Programming Language가 초급자들부터 봐야 하는 책으로 유명한 것에 비하여, C++의 창시자 비아네 스트로스트룹의 The C++ Programming Language는 절대 초급용 서적이 아닌, 중급 이후의 레퍼런스 서적이다. | |
이후 | 이 단계까지 성공적으로 도달했으면, 최종 목표에 따라서 책을 보아야 하는 단계이므로 더 이상 일반적인 추천이 가능하지 않다. |
사족으로, "Visual C++ (VC++)"이라고 굳이 제목에 Visual을 넣는 책들은 조금 오래된 서적들이니 주의할 것. "C/C++"이라고 C언어와 C++을 혼용해서 서술하거나, 명색이 C++ 참고서라면서 정작 내용은 C언어에 대한 것만으로 절반 가까이 채운 책들도 있는데, 이런 종류 역시 별로 추천하지 않는다. 기본적으로 MFC 위주의 오래된 책은 피해야 한다.
8. 방언 및 확장
I don't like dialects because the larger the community is, the more they can share and the better things are.
나는 방언을 좋아하지 않는다. 왜냐하면 커뮤니티가 더 커질수록, 더 많은 사람들이 공유할 수 있게 되고, 상황이 더 좋아지기 때문이다.
- Bjarne Stroustrup, Core C++ 2021
나는 방언을 좋아하지 않는다. 왜냐하면 커뮤니티가 더 커질수록, 더 많은 사람들이 공유할 수 있게 되고, 상황이 더 좋아지기 때문이다.
- Bjarne Stroustrup, Core C++ 2021
8.1. GPGPU를 위한 확장
8.1.1. CUDA
2007년 6월에 발표된 NVIDIA의 GPU에서 동작하는 C++ 기반 GPGPU 언어.8.1.2. OpenCL
2009년 8월에 발표된 개방형 GPGPU 언어. 원래는 C 기반이었으나 2015년 11월 16일에 발표된 OpenCL 2.1부터 C++14를 기반으로 문법이 확장되었다.8.2. 마이크로소프트의 방언
8.2.1. C++/CLI
2005년 비주얼 스튜디오 2005에 도입된 .NET Framework의 CLR에 맞물려 동작하는 C++. 보통 프레임워크 정도로 제공되는 다른 라이브러리와 달리 .NET의 메모리 구조에 맞추어 언어 자체가 다르다.2002년에 비주얼 스튜디오 .NET 2002에 도입되었던 Managed Extensions for C++[26]는 정말 못 써먹을 언어였기 때문에 Managed C++을 대체하기 위한 언어로 나왔으며, 적어도 스펙상으로는 게임을 만들기에도[27][28] 부족함이 없는 고속의 언어임에도 생산성은 C++에 비해서 높다고 한다. 특히 C#과 C++를 이어주는 래퍼 등의 모듈을 만들기에는 아주 제격이며, C/C++로 만들어진 프로젝트를 시간적 여유를 두고 닷넷 기반으로 바꾸는 용도로도 많이 쓰이고 있다. 필요에 따라 단계적으로 모듈을 바꿔치기 하다보면 어느새 순수 닷넷 애플리케이션 완성. 그러나 지원 및 이식성이 떨어져서 업계 표준으로 쓰기에는 무리다.
C++/CLI 코드 내에서는 관리와 비관리 클래스를 혼용할 수 있으므로 래핑 없이 모든 모듈을 C++/CLI로 작성해도 되지만, C++/CLI 내의 C++ 클래스는 순수 네이티브 라이브러리에서 만들어진 C++ 클래스에 비해 성능이 다소 떨어진다. 따라서 성능이 중요한 모듈은 별도의 네이티브 코드로 작성하고, C++/CLI는 이 모듈의 래핑을 담당하는 모듈만을 작성하는 것이 좋다.
8.2.2. C++/CX
2012년에 WinRT 및 XAML을 지원하기 위해 마이크로소프트에서 고안한 확장 언어. 라이브러리는 Windows Runtime C++ Template Library(WRL)을 사용했으나 2015년 6월 23일에 발표된 C++/WinRT로 대체되었다.8.2.3. C++/CL
공식적인 명칭은 아니다. 하지만 Visual Studio의 C++ 컴파일러는 C++ 표준에도 없는 문법을 지원하거나 C++표현에서 아예 명시적으로 금지된 문법까지 지원하고 있다. 예를 들자면 어떤 struct 또는 union안에 익명 struct/union을 만들고 이 멤버에 접근하는 것은 ISO C++ 구현에서 명시적으로 금지되어 있지만[ISO/IEC][30] Visual Studio cl.exe는 이런 표준 위반을 상관하지 않는다.이러한 이유로 GCC/Clang에서 컴파일 되는 코드는 MSVC에서 컴파일 되지만 MSVC에서 컴파일 되는 코드는 GCC/Clang에서 컴파일이 되지 않거나 경고를 내는 경우가 잦다.
9. 관련 문서
- C(프로그래밍 언어)
- 인라인 함수
- 표준 라이브러리
- 템플릿
- 컴퓨터공학과[31]
- 객체 지향 프로그래밍
- Carbon[32]
- F-35 - F-35의 소프트웨어는 예외적으로 Ada가 아닌 C++로 프로그래밍 되어있다.
10. 외부 링크
11. 둘러보기
프로그래밍 사이트 선정 프로그래밍 언어 순위 목록 | ||||
{{{#!wiki style="margin: 0 -10px -5px; word-break: keep-all" {{{#!wiki style="display: inline-table; min-width: 25%; min-height: 2em;" {{{#!folding [ IEEE Spectrum 2024 ] {{{#!wiki style="margin: -5px 0" | <rowcolor=#fff> 스펙트럼 부문 상위 10개 프로그래밍 언어 | 직업 부문 상위 10개 프로그래밍 언어 | ||
1 | Python | 1 | SQL | |
2 | Java | 2 | Python | |
3 | JavaScript | 3 | Java | |
4 | C++ | 4 | TypeScript | |
5 | TypeScript | 5 | SAS | |
6 | SQL | 6 | JavaScript | |
7 | C# | 7 | C# | |
8 | Go | 8 | HTML | |
9 | C | 9 | Shell | |
10 | HTML | 10 | C++ |
}}}
}}}
- [ Stack Overflow 2024 ]
- ||<tablewidth=100%><width=9999><-4><bgcolor=#FFA500><tablebgcolor=#fff,#222> 2024년 Stackoverflow 설문조사 기준 인기 상위 25개 프로그래밍 언어 ||
1 JavaScript 14 Rust 2 HTML, CSS 15 Kotlin 3 Python 16 Lua 4 SQL 17 Dart 5 TypeScript 18 어셈블리어 6 Bash 19 Ruby 7 Java 20 Swift 8 C# 21 R 9 C++ 22 Visual Basic 10 C 23 MATLAB 11 PHP 24 VBA 12 PowerShell 25 Groovy 13 Go
- [ TIOBE 2024 ]
- ||<tablewidth=100%><width=9999><-4><bgcolor=deepskyblue><tablebgcolor=#fff,#222> 2024년 8월 기준 검색어 점유율 상위 20개 프로그래밍 언어 ||
1 Python 11 MATLAB 2 C++ 12 Delphi / Object Pascal 3 C 13 PHP 4 Java 14 Rust 5 C# 15 Ruby 6 JavaScript 16 Swift 7 SQL 17 Assembly language 8 Visual Basic 18 Kotlin 9 Go 19 R 10 Fortran 20 Scratch {{{#!wiki style="margin: 0 -10px -5px; min-height: calc(1.5em + 5px);"
{{{#!folding [ 21위 ~ 50위 펼치기 · 접기 ]
{{{#!wiki style="margin: -5px -1px -11px"21 COBOL 36 Scala 22 Classic Visual Basic 37 Transact-SQL 23 LISP 38 PL/SQL 24 Prolog 39 ABAP 25 Perl 40 Solidity 26 (Visual) FoxPro 41 GAMS 27 SAS 42 PowerShell 28 Haskell 43 TypeScript 29 Dart 44 Logo 30 Ada 45 Wolfram 31 D 46 Awk 32 Julia 47 RPG 33 Objective-C 48 ML 34 VBScript 49 Bash 35 Lua 50 Elixir
- [ PYPL 2024 ]
- ||<tablewidth=100%><width=9999><-4><bgcolor=green><tablebgcolor=#fff,#222> 2024년 8월 기준 검색어 점유율 상위 20개 프로그래밍 언어 ||
1 Python 11 Objective-C 2 Java 12 Go 3 JavaScript 13 Kotlin 4 C# 14 MATLAB 5 C/C++ 15 PowerShell 6 R 16 VBA 7 PHP 17 Dart 8 TypeScript 18 Ruby 9 Swift 19 Ada 10 Rust 20 Lua
}}} ||
프로그래밍 언어 목록 · 분류 · 문법 |
TIOBE 선정 올해의 프로그래밍 언어 / C++ | |||||
{{{#!wiki style="margin: 0 -10px -5px; min-height: 26px;" {{{#!folding [ 펼치기 · 접기 ] {{{#!wiki style="margin: -6px -1px -11px; word-break: keep-all;" | 없음 | → | 2003년 C++ | → | 2004년 PHP |
2021년 Python | → | 2022년 C++ | → | 2023년 C# |
[1] 덴마크인이라 이름 역시 덴마크어이며, 북유럽권 언어가 그렇듯이 영미권에서도 상당히 난해하게 들리는 이름이다. 스트로스트룹이라는 이름은 그냥 알파벳 철자대로 영미식 발음으로 읽은 것이라 원래 발음과는 상당히 다르다. 이름 발음을 물어 보는 경우를 하도 많이 들었는지 아예 본인이 자기 사이트에 wav 파일로 이름 읽는 법을 올려두었다. 대한민국 웹 역시 그냥 영미권 발음대로 적거나 아예 음역조차 하지 않고 알파벳 그대로 적어두기도 한다.[2] 간단하게 'C=C+1' 정도 의미다. 수학교육과 등에서는 '다음수'라는 개념으로 가르친다.[3] 그러나 실상 C++11 이후의 모던 C++ 기능을 가르쳐주는 곳이 매우 드물어서 C++의 객체 지향만 조금 배울 수 있다. C++의 객체 지향은 다른 언어에 비해서 좀 더 복잡하다. 제대로 다루기 위해서는 별도의 서적을 참고하는 것이 권장되며, 실제 프로젝트의 코드에 대해 탐구하고 경험해보는 것이 좋다. C++를 모르면 2학년부터는 강의를 전혀 이해할 수 없기 때문에 의외로 많은 학생들이 중도포기를 하게 되며 컴공을 나왔는데도 프로그래밍을 전혀 못하는 학생들이 수두룩하게 발생하고 있다.[4] GCC의 libstdc++, Clang의 libc++로 대표되는 현재의 모던 C++ 표준 라이브러리가 스테파노프(Stephanov)와 리(Lee)가 1990년대에 개발한 Standard Template Library(STL)의 아이디어를 많이 수용한 것은 사실이나, C++의 표준안 그 어디에도 STL이라는 표현은 등장하지 않는다. Effective C++의 저자인 스콧 마이어스(Scott Meyers)와 같이 나이 많은 거장 프로그래머들이 1990년대의 관습 그대로 STL이라는 용어를 자신의 저작물에 지속적으로 사용하는 바람에 STL이라는 용어가 아직도 널리 사용되고 있으나, STL과 C++ 표준 라이브러리의 차이가 뭔지 묻는 수많은 구글 검색 결과가 보여주듯이 초보자들에게 꽤 커다란 혼돈을 주는 요소이다. 스테파노프와 리가 직접 작성한 Hewlet-Packard 버전의 STL이나, 실질적으로 더 널리 쓰이던 Silicon Graphics 버전의 SGI STL은 더 이상 관리가 되지 않고 방치가 된 지 오래이고, SGI STL을 계승하려고 노력하던 STLPort도 개발이 중단되었다. 결국 초창기 STL의 구현체는 모두 사라지고 그 아이디어만이 살아남아서 C++의 표준 라이브러리에 흡수되었으므로, STL을 따로 떼어 지칭하는 것이 이제 의미가 없다. 각각의 '하위 언어' 들의 규칙과 구현이 전부 다르므로 복잡도가 상당히 높으며 'C with classes'라는 초기 명칭과는 한참 차이가 날 정도로 확장되었다.[5] 다만 C에서 C++의 방법론을 따라가지 못하는 건 아니다. GNOME의 핵심 라이브러리인 Glib이 대표적으로, C 언어로 객체 지향을 짜도록 구성되어 있다. incomplete type declaration 트릭을 이용하여 캡슐화를 흉내내고, 매크로와 컴파일러 확장을 이용해서 type-generic function을 만들어 쓰고, struct hack을 이용하여 vector를 흉내 내는 식이다. 그러나 저런 트릭은 언어 차원에서 정식으로 제공한다기보다 말 그대로 '트릭'에 가까우므로 이상한 조건들이 붙는 경우가 종종 있고, 그것들을 정확히 파악하고 있지 않으면 상당히 찾아내기 어려운 에러를 내는 경우도 많다.[6] C99에서 추가된 지정 초기자(Designated Initializers)[iostream] [stdio.h] [9] 시간 제한이 빡빡한 PS(문제풀이) 쪽에서는 거의 매번 쓰일 정도인 기능이지만 Visual Studio에서는 의미 없으니 참고. #[10] Smalltalk에서는 모든 클래스는 최상위 클래스를 상속받으며, 클래스가 가진 모든 메타 정보를 어디에서나 접근할 수 있다. Smalltalk의 클래스는 편의상 자료형으로 취급되지만 사실 클래스도 어떤 객체로부터 생성되는 인스턴스다. 클래스에 대해 메타 정보를 서술하는 메타클래스가 존재하며, 이를 외부 인터페이스로 내보이는 Reflection을 구현한다. 즉 Smalltalk의 클래스는 네이티브하게 런타임 인스턴스의 속성만 정의해놓은 것이 아니라, 클래스도
new GameObject
마냥 생성되는 인스턴스일 뿐이다.[11] 다만 해당 언어들조차 파일 입출력에서는 별도의 소멸자, 파괴 메서드, 예외 처리의 도움이 필요하다.[12] 원본 객체가 필요없는 경우, 새로 객체를 생성할 때 깊은 복사 없이 기존 객체의 메모리를 재활용할 수 있도록 하는 기능이다.[13] 또한 레퍼런스 카운팅으로 인해 발생하는 std::shared_ptr
의 순환 참조 문제를 피하기 위해서 참조만 할 뿐 소유권은 지니지 않는 std::weak_ptr
도 지원한다. std::weak_ptr
은 객체 대신 std::shared_ptr
을 참조한다고 보면 된다. 하나의 std::shared_ptr
과 다수의 std::weak_ptr
을 사용하면 여러 소유권자가 하나의 객체를 공유하면서도 순환 참조 문제를 해결할 수 있다.[14] '클래스의 인스턴스'가 아니다.[15] 변수[16] 자료형[17] 메모리 정렬 방식, 사용자가 접근할 수 있는 메모리 영역, 바이트 크기, 메서드의 이름과 코드, 필드의 이름과 정보[18] 이를 '결정적'이라고 한다[19] 이를 '비결정적'이라고 한다[20] Functor, Niebloid, Function Object. () 연산자 오버로딩을 통해 함수 인터페이스를 구현한다[21] GCC와 같은 컴파일러는 최적화 옵션을 넣지 않을 경우 constexpr
함수를 컴파일 시점에 계산하지 않는데, 아래와 같이 템플릿을 섞어서 사용하면 확실히 컴파일 시점에 계산된다.[22] C#을 스트립트 언어로 쓰는 유니티 엔진도 내부 소스는 C++로 이루어져 있다. 즉, 스크립팅용으로만 C#을 쓰는 셈이다. 심지어 C#으로 짜놓은 코드를 C++로 변환하는 IL2CPP라는 기능도 제공한다.[23] 시스템, 실시간 임베디드, 게임, 파이낸스, 그래픽, 머신러닝, 영상처리, 수치 시뮬레이션...[24] 대학 교수, 조교에게만 제공이 된다고 한다.[25] 하지만 한국어판은 번역 오류가 많아 이해가 어려울 수도 있다.[26] 줄여서 Managed C++라고도 불렀다.[27] 게임은 일반적으로 생산성이 매우 중요한 거대 프로젝트이면서 하드웨어의 성능을 극한까지 끌어내야 하는, 속도와 효율에 매우 민감한 특수한 소프트웨어 분야이기 때문에 C++가 많이 사용된다. 괜히 이런 이야기에 게임에 대한 언급이 잘 나오는 게 아니다.[28] 초기의 Managed C++은 언어의 포지션도 상당히 애매했다. 간단히 말하자면 닷넷 프레임워크와 레거시 운영체제 프레임워크를 동시에 지원하고자 했으나 결과는 이도저도 아니었다. 차라리 닷넷 프레임워크가 COM을 지원하니 그런 걸 쓰는 게 낫다.[ISO/IEC] JTC1 SC22 WG21 N 4860 §11.5.1 Anonymous unions[30] 해당 표현은 C11에서는 표준이나 C++는 아니다.[31] 대부분의 컴공과에서 배운다. 많은 컴공과에서 첫 언어로 C를 가르치는 관계로, 학생들에게 익숙한 C의 문법을 가지고 객체 지향 프로그래밍의 개념도 다룰 수 있다는 장점이 있기 때문이다. Java나 Python을 처음으로 배우는 학교의 경우에도 언젠가 한번쯤은 C나 C++를 건드릴 일이 생기게 된다.[32] C++의 슈퍼셋이며, 본 사이트에선 C++의 후계자라고 설명한다. Java에서 Kotlin으로, 자바스크립트에서 타입스크립트로 바뀐 것과 비슷하다고 한다.