시리즈:쉽게 배우는 프로그래밍 입문/C++

Nyeong (토론 | 기여)님의 2015년 5월 17일 (일) 13:53 판 (Ruby 링크 추가)

문서의 내용이 너무 쉬워서 오늘부터 프로그래밍 할 수 있을 것 같습니다.

이 문서에는 독자적으로 연구한 내용이 들어갑니다. 다른 사람의 의견을 존중하면서 무례하지 않도록 작성해 주시고, 의견 충돌 시 토론 문서에서 토론해 주세요.

이 언어를 배우려는 사람에게 전하는 주의사항

C 문법을 그대로 사용하는 경우

물론 프로그래밍을 할 수는 있다. 그렇지만, C의 문법보다 형변환[1] 조건이 빡빡하다던가, C++의 많은 기능을 사용할 수 없다던가 하는 점이 있기 때문에, 정말 C로 개발해야만 하는 상황(거의 없겠지만)이 아니라면 C++의 문법을 사용하는 것이 좋다.

객체지향은 또 뭐야?

쉽게 말해, 모든 대상을 "데이터"와 "기능"으로 추상화해서 나타낸 것이다. 기존의 C에서 사용하던 구조체(struct)는 말 그대로 단순히 데이터를 담는 "자료형"의 역할을 했지만, 클래스는 어떤 대상을 데이터와 기능의 집합으로 나타내므로 그 대상의 성질, 특성과 같은 것들을 표현할 수 있다.

쓸데없이 불친절하고 어려운 템플릿

템플릿은 메타프로그래밍 요소로, 서로 다른 여러가지의 클래스에 대해 각각을 따로 프로그래밍하지 않고 같은 이름을 가지는 대상(클래스, 함수)으로 프로그래밍할 수 있게 한다. 다시 말해서, 일반화 프로그래밍이 가능하다! 하지만, C++의 템플릿은 다른 여타 언어들의 메타프로그래밍 요소와는 달리 템플릿 메타프로그래밍이라는 변태짓을 가능하게 한다.나쁜 녀석들 같으니라고 구글링을 해도 답이 안나온다 이 기법은 C++ 프로그래머 중에서도 정말 고수들만이 제대로 활용할 수 있으므로, 공부하려고 마음먹었을 때 각오하는 것이 좋다.하지만 우리 회사는 못하게 하는데 그럴때는 실력에 대한 신뢰감을 줘야..

함수형 프로그래밍은 또 어디에서 굴러들어온건데?

시간이 지나면서, 프로그래머들은 객체지향의 한계에 봉착하게 된다. 대세는 멀티코어! 다들컴맹 빼고 들어봤을 것이다. 멀티코어 프로그래밍은 서로 다른 프로세스가 하나의 데이터에 동시에 접근하는 경우가 비일비재하기 때문에[2] 접근 통제를 위해 프로세스들을 락/언락해야만 한다. 그런데 락/언락을 자주 하게 되면 CPU에서 병목현상이 발생하기 때문에 프로그램의 실행시간, 반응 속도 등에 영향을 끼치게 된다.

이 멀티코어 프로그래밍을 위한 대안이 바로 함수형 프로그래밍이다. 함수형 프로그래밍에 사용되는 함수는 수학에서의 함수의 성질을 따른다. 기존의 함수는 모든 작업을 순차적으로 처리해야만 했지만, 함수형 프로그래밍에서는 작업 순서를 변경시켜서 어떤 것을 먼저 처리하고 어떤 것을 지연시켜도 같은 결과가 나오는 것이다!

더럽게 기능이 많은데, 이 많은 걸 언제 배워!

그래서 C++의 진입장벽이 높은거다. 현재진행형으로 언어 표준을 개정해나가면서 짧은 시간에 많은 기능이 추가되거나, 바뀌거나, 사라지고 있다. 하지만, "C++스러운" 프로그래밍 방법은 표준을 개정해나가도 크게 변하지 않는다. 표준은 "C++스러운" 방법을 위한 편의 기능을 제공하는 방향으로 개정되고 있다고 생각해도 된다. 그러니, "C++스러운" 방법이 무엇인지 안다면, 앞으로 계속 표준이 바뀌더라도 학습이 용이할 것이다.

많은 내용들 중 중심적인 내용을 먼저 학습한 후, 곁가지로 제공되는 기능을 익혀나가는 방법은 C++을 공부하는 좋은 방법 중 하나이다. C를 빠르게 공부한 후, C++의 중심적 내용인 클래스를 공부하면 나머지는 다 부가기능처럼 보일것이다.

준비

Visual Studio 커뮤니티 2013

개인 사용자들에게는 무료로 공개되어있는 버전이다. 참고로 이거 하나면 C++ 뿐만이 아니라 C#, VB.NET 개발도 가능하다.

최신 표준의 기능들을 사용하고 싶다면 컴파일러를 LLVM로 바꾸면 된다.

후술된 내용들을 보기 전에 위의 C 프로그래밍 내용을 숙지하자. C++은 기본적으로 C에서 기원했다.

예외란 없다Hello, World!

빈 프로젝트를 생성한 후 소스(.cpp)파일에 다음 내용을 작성한다.

#include <iostream>

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

새 표준 입출력

iostream을 인클루드하고 사용한다.[3]

표준 출력

std::cout << [기본 자료형 변수/상수];

기본적으로 이 형식으로 사용한다. 기본 자료형이 아닌 구조체, 클래스 등은 후술할 오버로딩 참고.

std::cout << [출력 대상] << [출력 대상] << ...

이렇게 여러 대상의 출력을 한 줄에 작성할 수 있다.

std::cout << ... << std::endl;

이렇게 작성하면 중간의 출력대상을 모두 출력한 후 한 줄을 강제 개행한다.

표준 입력

상수

기존의 const에 더해, volatile과 mutable 키워드를 사용할 수 있게 되었다. mutable 키워드의 경우 후술할 클래스 부분을 참고.

volatile 키워드를 사용한 변수는 그 값이 언제든지 바뀔 수 있다는 것을 컴파일러에게 명시적으로 전달해주기 때문에, 최적화를 방해한다. goto 키워드처럼 쓰면 방해되는 키워드이기 때문에 이런 키워드는 없다고 생각하고 프로그래밍하자.

좌측값, 우측값

C++11이 제정되며 강조되는 개념이다. 절대로 없던게 아니다! C부터 있던 유서깊은(?) 개념이다.

좌측값(L-Value)는 변수나 변수의 주소 등 확실하게 메모리에 위치한 주소를 가진 변수이다. C에서 사용되던 일반적인 변수를 떠올리면 된다. 반면, 우측값(R-Value)는 그 외의 모든 임시변수메모리에 위치하지 않은 것들인 상수를 포함한다. 임시변수에 대한 자세한 개념은 추가바람. 더욱 엄밀하게 말하자면, 좌측값은 식 한 줄이 실행된 후에도 남아있는 값이고, 우측값은 식 한 줄이 실행되고 나면 소멸하는 값이다.

사실, 좌측값, 우측값이란 이름은 대입 연산자를 기준으로 올 수 있는 방향에 따라 지어졌다. 좌측값은 대입 연산자 왼쪽, 오른쪽 다 올 수 있지만, 우측값은 오른쪽에만 올 수 있다. 따라서, 대입 연산자 왼쪽에는 좌측값만 올 수 있다. 또한, 좌측값은 메모리상에 위치한 주소가 정해져 있으므로 변수로 선언할 수 있지만, 우측값은 그러지 못한다. 그러나, 함수의 인자로 오거나 반환값으로 오는 것은 가능하다. 앞으로 후술할 템플릿에도 사용할 수 있다.

이 개념을 직접 언어적 측면에서 도입함으로써, C++은 임시변수의 생성을 위한 메모리와 시간을 절약할 수 있게 되었다.

레퍼런스

대놓고 이름만 봐도 참조에 의한 호출(Call-by-Reference)[4]에서 사용하기 위해 만들어낸 개념이라는 것을 알 수 있다. 포인터가 있는데 굳이 레퍼런스를 만든 이유는 모르겠으나[5], 오로지 참조에 의한 호출만을 사용하기 위해 디자인되었다는 점은 확실하다.

사용법을 포인터와 비교하면 다음과 같다.

int q;
int *p;// 포인터, 가능
int &p;// 레퍼런스, 불가능, 선언시 초기화해야 함
int *p = &q;// 포인터, 가능
int &p = q;// 레퍼런스, 가능

가장 많이 쓰이는, 함수에서의 사용 예는 다음과 같다.

int f(const int n);// 임시값, 반환도 임시값
int f(const int& n);// 좌측값, 반환은 임시값
int f(const int&& n);// 우측값, 반환은 임시값

int& f(const int n);// 임시값, 반환은 좌측값
int& f(const int& n);// 좌측값, 반환도 좌측값
int& f(const int&& n);// 우측값, 반환은 좌측값

int&& f(const int n);// 임시값, 반환은 우측값
int&& f(const int& n);// 좌측값, 반환은 우측값
int&& f(const int&& n);// 우측값, 반환도 우측값

이름공간

그동안 사용하던 static 키워드에서 탈피할 수 있게 해주는 표준 문법이다. static은 해당 파일에서만 전역인 것처럼 사용할 수 있게 하였지만, 이름공간은 무려, 인클루드만 해주면 어디에서나 사용할 수 있다! 심지어 변수, 함수, 클래스 등을 용도별로 모을 수도 있다.

가장 대표적인 이름공간으로, C++ 표준 라이브러리의 이름공간인 std가 있다.

공용체, 열거형

클래스

예외처리

템플릿

람다

고급 과정

  1. 간단히 설명하자면, 문자를 정수로 바꾸는 등의 한 데이터 타입을 다른 타입으로 변환하는 것을 말한다.
  2. 이렇게 되면 프로그램을 여러번 실행시켰을 때 같은 조건에서도 항상 같은 결과가 나온다고 기대할 수 없다.
  3. 뒤에 .h 붙이지 말자. 구식 표준이다.
  4. 주소를 저장하는 변수의 종류인 포인터, 레퍼런스를 이용해서 그 주소에 위치한 값을 호출하는 방식, 값에 의한 호출(Call-by-Value)와는 반대개념
  5. 추가바람