[C++] Chapter 01 정리
C++에서 입/출력 방식
C++에서는 C언어와 달리 기본 헤더 파일이 <stdio.h>가 아닌 <iostream>이고, printf와 scanf를 대체하는 std::cout, std::cin이 존재한다. 그리고 cin/cout을 통한 입/출력에는 별도의 포맷 지정이 필요하지 않다.
#include <iostream>
int main() {
int num = 20;
std::cout << "Hello World!" << std::endl;
std::cout << "Hello " << "World!\n";
std::cout << num << " A";
std::cout << " 3.14\n";
return 0;
}
지역 변수 선언
C언어에서는 지역변수의 선언이 가장 먼저 등장해야했지만 C++에서는 지역변수의 선언 위치에 제한을 두지 않는다.
#include <iostream>
int main() {
int val1, val2;
int result = 0;
std::cout << "두 개의 숫자입력: ";
std::cin >> val1 >> val2;
if (val1 < val2) {
for (int i = val1 + 1; i < val2; i++)
result += i;
}
else {
for (int i = val2 + 1; i < val1; i++)
result += i;
}
std::cout << "두 수 사이의 정수 합: " << result << std::endl;
return 0;
}
함수 오버로딩(Function Overloading)
C언어에서 함수는 함수명으로 구분되지만 C++에서는 매개변수의 타입과 개수로 구분되기 때문에 동일한 이름의 함수 정의가 허용되고, 이를 함수 오버로딩(Function Overloading)이라고 한다.
#include <iostream>
void swap(int& a, int& b) {
int tmp;
if (a < b) {
tmp = a;
a = b;
b = tmp;
}
}
void swap(char& a, char& b) {
char tmp;
if (a < b) {
tmp = a;
a = b;
b = tmp;
}
}
void swap(double& a, double& b) {
double tmp;
if (a < b) {
tmp = a;
a = b;
b = tmp;
}
}
매개변수의 디폴트 값(Default Value)
함수를 사용할 때 함수의 매개변수 선언에 값을 지정함으로 써 해당 인자가 전달되지 않으면 지정된 값이 전달된 것으로 판단하여 작동할 수 있다.
매개변수의 디폴트 값을 지정할 때에는 아래의 규칙을 지켜야한다.
- 함수의 선언 부분에 위치해야한다.
- 선언된 매개변수의 수보다 적은 수의 인자가 전달되었을 시 전달되는 인자는 왼쪽에서부터 채워지기 때문에 디폴트 값은 오른쪽부터 채워나가야한다.
#include <iostream>
int BoxVolume(int length, int width = 1, int height = 1);
int main() {
std::cout << "[3, 3, 3] : " << BoxVolume(3, 3, 3) << std::endl;
std::cout << "[5, 5, D] : " << BoxVolume(5, 5) << std::endl;
std::cout << "[7, D, D] : " << BoxVolume(7) << std::endl;
//모든 값에 디폴트 값이 지정된 것이 아니기에 아래는 컴파일 에러가 발생한다.
//std::cout << "[D, D, D] : " << BoxVolume() << std::endl;
return 0;
}
int BoxVolume(int length, int width, int height) {
return length * width * height;
}
인라인(Inline) 함수
C언어의 매크로 함수를 일반 함수처럼 정의할 수 있도록 만든 것이다.
#include <iostream>
inline int SQUARE(int x) {
return x * x;
}
int main() {
std::cout << SQUARE(5) << std::endl;
std::cout << SQUARE(12) << std::endl;
return 0;
}
이름공간 / 네임스페이스(namespace)
이름공간, 즉 네임스페이스란 함수 이름이 같아서 발생하는 이름충돌을 방지하기 위해 만들어진 문법적인 요소이다.
네임스페이스는 아래의 특성을 가진다.
- 동일한 네임스페이스에 정의된 함수를 호출할 때는 네임스페이스를 명시할 필요가 없다.
- 네임스페이스는 다른 네임스페이스 안에 삽입될 수 있다. 즉, 네임스페이스는 중첩될 수 있다.
- 범위 지정 연산자 :: 을 이용해 네임스페이스를 지정한다.
- using을 통해 네임스페이스을 지정하지 않고 호출하겠다는 것을 명시할 수있다.
#include <iostream>
namespace Bcom {
void SimpleFunc(void);
}
namespace Bcom {
void PrettyFunc(void);
}
namespace Pcom {
void SimpleFunc(void);
}
int main() {
Bcom::SimpleFunc();
return 0;
}
void Bcom::SimpleFunc() {
std::cout << "Bcom이 정의한 함수" << std::endl;
PrettyFunc();\
Pcom::SimpleFunc();\
}
void Bcom::PrettyFunc() {
std::cout << "So Pretty~" << std::endl;
}
void Pcom::SimpleFunc() {
std::cout << "Pcom이 정의한 함수" << std::endl;
}
using
네임스페이스의 지정 없이 함수를 호출하겠다는 것을 선언하는 데 사용되는 키워드이다.
#include <iostream>
using namespace std;
int main() {
cout << "범위 지정 연산자 없이도 네임스페이스 std에 정의된 함수를 호출";
return 0;
}
개인적인 추가 내용
C++에서도 <stdio.h>나 <cstdio> 헤더파일을 사용해 printf와 scanf를 사용할 수 있으며 아래 그림을 통해 알 수 있듯 printf와 scanf에 비해 cout, cin은 현저히 느린 속도를 가진다.
이는 cin/cout이 stdio.h와 iostream 두 개의 버퍼를 같이 사용하여 동기화 유지하는 작업이 추가되어 있기 때문인데 이를 해결하기 위해 printf / scanf를 사용하거나 아래 코드를 통해 cin / cout의 stdio.h와의 동기화를 해제시켜주면 된다.
ios::sync_with_stdio(false);
cin.tie(NULL);
단, 이 방식을 사용할 경우 c의 입출력방식(printf, scanf 등)과 같이 사용할 수 없게 되고, 싱글 스레드 환경에서만 사용 가능하기 때문에 실무에서는 사용해선 안되고 코딩테스트같은 알고리즘 문제에서만 사용해야한다.