C에서 C++로

입출력

#include <iostream>

int main(void) {
	// 출력
	std::cout << "Hello " << "World!" << std::endl;

	// 입력
	int num;
	std::cout << "cInput: ";
	std::cin >> num;
	std::cout << "num: " << num << std::endl;

	return 0;
}
Hello World!
cInput: 3
num: 3

C와 달리 헤더 파일에 .h 확장자를 생략한다. 여기서 사용한 iostream은 C++에서 사용되는 표준 입출력 라이브러리이다.  

출력은 cout, 입력은 cin을 사용한다. 그리고 "int num;"과 함수 중간에 지역 변수를 선언하는 것이 가능하다. (C의 경우, 일부 컴파일러에 한해 허용되지 않는 경우도 있었다.)

<<은 출력, >>는 입력을 의미하며 endl는 개행 후, 버퍼를 지운다. 

[ 백준 2741 ] 문제는 자연수 N을 입력 받아 1~N까지 출력하는 문제이다. 그런데 아래 코드는 시간초과가 난다. 

#include <iostream>

int main(void) {
	int num;
	std::cin >> num;
    
	for (int i = 1; i <= num; i++) {
		std::cout << i << std::endl;
	}
	return 0;
}

하지만 출력 구문을 아래와 같이 바꾸면 통과가 된다. 

std::cout << i << "\n";

std::endl는 개행 문자를 출력할 뿐만 아니라 버퍼를 지우며 시간을 소모하기 때문이다.


함수

C 언어는 함수명을 통해 호출한 함수를 찾고, C++는 함수명과 매개변수를 통해 찾는다. 따라서 C++에서는 함수명이 같지만 매개변수가 다른 두 함수를 만들 수 있다. 이것을 함수의 Overloading이라고 한다. 다만, 함수의 반환 자료형이 다른 두 함수를 구분하지는 않는다. 

#include <iostream>

void PrintNum(int n) {
	// 함수 1
	std::cout << "n: " << n << std::endl;
}

void PrintNum(int n1, int n2) {
	// 함수 2
	std::cout << "n: " << n1 << ", " << n2 << std::endl;
}

int main(void) {
	PrintNum(1);  // 함수 1
	PrintNum(7, 9);  // 함수 2
	return 0;
}

함수 파라미터의 default 값을 설정할 수도 있다. 함수 호출 시 인자를 전달하지 않을 때 사용할 값을 함수의 선언부에서 미리 지정한다. 

#include <iostream>

void PrintNum(int n1, int n2=3);

int main(void) {
	PrintNum(7);
	return 0;
}

void PrintNum(int n1, int n2) {
	std::cout << "n: " << n1 << ", " << n2 << std::endl;
}

inline 함수는 C의 매크로 함수를 정의하는 방식으로, C의 매크로 함수보다 더 명확한 정의가 가능해졌다. 하지만 매크로 함수가 전처리 단계에서 치환되는 것과 달리 인라인 함수는 컴파일 단계에서 처리된다. 또한 아래 코드에서도 보듯이 변수의 자료형을 강제하게 된다. 

#include <iostream>

// macro 함수
#define MUL(x, y) ((x) * (y))

// inline 함수
inline int multiply(int x, int y) {
	return x * y;
}

int main(void) {
	std::cout << "3*5: " << MUL(3, 5) << std::endl;
	std::cout << "3*5: " << multiply(3, 5) << std::endl;
	return 0;
}

Bool

bool 자료형이 추가되었다. true와 false는 각각 참과 거짓을 의미한다. 

int main(void) {
	bool positive = true;
	bool negative = false;
	cout << "True: " << positive << endl;  // 1 
	cout << "False: " << negative << endl;  // 0
	return 0;
}

참조

참조는 &을 이용해 데이터를 참조하는 변수명을 추가로 생성할 수 있도록 해준다. 

int main(void) {
	int num = 30;
	int *ptr = &num;
	int& ref = num;

	cout << "num: " << num << endl;  // 30
	cout << "*ptr: " << *ptr << endl;  // 30
	cout << "ref: " << ref << endl;  // 30

	num = 6;
	cout << "num: " << num << endl;  // 6
	cout << "*ptr: " << *ptr << endl;  // 6
	cout << "ref: " << ref << endl;  // 6
	return 0;
}

위 예시에서 num과 ref는 데이터를 의미한다. 

int& GetOne(void) {
	int one = 1;
	return one;
}

int main(void) {
	int &num = GetOne();
	cout << "GetOne(): " << num << endl;  // GetOne(): -858993460
	return 0;
}

위 예시의 경우, one 변수를 참조하는 num을 출력했더니 관련없는 값이 출력되었다. one의 경우, GetOne의 지역변수이기 때문에 함수의 호출이 종료되면 소멸된다. 따라서 num은 의미없는 값을 참조하게 된다. 


new, delete

malloc는 new, free는 delete와 유사한 역할을 한다. 동일하게 작동하지는 않는다. 

char* str = new char[100];
delete []str

new를 통해 생성된 배열의 주소를 str에 할당하고, delete를 통해 str로 참조된 배열의 할당을 해제한다. 

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>

using namespace std;

char* MakeEmptyStr(int len) {
	char* str = new char[len];
	return str;
}

int main(void) {
	char* str = MakeEmptyStr(16);
	strcpy(str, "Hello World!");
	cout << str << endl;
	delete []str;
	return 0;
}

MakeEmptyStr은 문자열을 할당하고 main 함수에서 메모리를 사용할 수 있도록 하고 있다.