1. 변수 선언을 변수를 쓰기 전이라면 어디에서 해도 된다. (원래는 스코프 처음에 해야만 했다.)
C스타일 | Cpp스타일 |
int main() { int result, a = 3, b = 4;int i; result = a + b; for (i = 0; i < 10; i++) { result += i; } return 0; } |
int main() { int result, a = 3, b = 4; result = a + b; for (int i = 0; i < 10; i++) { result += i; } return 0; } |
2. 'bool형'이 추가되었다. bool형은 참과 거짓만을 갖는 자료형이다.
C언어에서는 C99에서 stdbool.h 를 포함하면 사용할 수 있다.
3. 'reference'가 추가되었다. 'reference'란 변수에 새로운 별칭을 지어주는 것이다.
#include <stdio.h>
void decR(int& R) { R--; }
void constR(const int& R) { }
int& returnR_1(int& R) { return R; }
int returnR_2(int& R) { return R; }
int main() {
int iA = 0, iB = 1;
int &rA = iA; //컴파일 에러 (초기화되지 않은 참조자 선언이다.)
//int &rB; //컴파일 에러 (참조자가 상수를 가리킬 수 없다.)
//int &rC = 10; //참조자를 이용한 값 변경
rA = 10;
printf("%d \n", iA); //함수의 매개변수가 참조자 %주소로 넘기지 않아도 된다.
decR(iB); //컴파일 에러! 상수를 넘길 수는 없다.
//decR(10); //참조가가 가리키는 변수를 바꿔봤다.
printf("%d \n", rA);
rA = iB;
printf("%d \n", rA); //상수 참조자
//상수 참조자는 상수를 참조할 수 있다.
const int& rD = 10;
//함수의 매개변수가 상수 참조자. %매개변수로 상수를 넘길 수 있다.
constR(10); //함수의 반환값이 참조자여야 할 때 = 반환값을 참조자에 대입해야 할 때
int& rE = returnR_1(rA); //컴파일 에러 (반환값이 상수인 것과 같다.)
//int& rF = returnR_2(rA);
}
4. 'namespace'와 'using' 키워드, ' :: 연산자(Scope Resolution Operator)'가 추가되었다.
namespace : 특정 영역의 범위를 지정하고 이름을 붙여준 것.
using : 기본적으로 사용할 namespace를 지정함.
(namespace A)::(식별자 B) : namespace A에 있는 식별자 B를 사용하겠다.
#include <iostream>
int var = 0;
int main() {
int var = 10;
std::cout << var << std::endl; //지역변수 var출력
std::cout << ::var << std::endl; //전역변수 var출력
}
5. 메모리 할당 연산자인 'new'와 'delete'가 추가되었다.
Cpp의 new는 C언어의 malloc함수를 대신하고, delete는 free함수를 대신한다.
6. '함수 중복 정의(Function Overloading)'가 가능해졌다.
함수명이 같고, 시그니처는 다른 함수를 정의하는 것. (시그니처(signature) : 매개변수의 개수, 타입, 순서)
함수의 반환형만 다르게 하는 것으로는 컴파일러가 구분할 수 없기 때문에 중복 정의가 되지 않는다.
#include <iostream>
//매개변수의 갯수가 다름
void a() {
std::cout << 'a' << std::endl;
}
void a(int i) {
std::cout << i << std::endl;
}
//매개변수의 타입이 다름
void b(int i) {
std::cout << i << std::endl;
}
void b(double i) {
std::cout << i << std::endl;
}
//매개변수의 순서가 다름
void c(int i, double d) {
std::cout << i << std::endl;
}
void c(double i, int d) {
std::cout << i << std::endl;
}
//리턴 타입만 다름 (구분 안 됨)
void d() {
std::cout << 0 << std::endl;
}
//int d() {
std::cout << 'c' << std::endl;
}
int main() {
a(); a(1);
b(2); b(2.5);
c(3, 3.5); c(4.5, 4);
d();
}
7. 함수의 매개변수에 기본값을 줄 수 있게 되었다. ('디폴트 매개 변수'라고 한다.)
(이게 문법은 간단한데, 함수 오버로딩과 엮이면 좀 복잡해진다.)
#include <iostream>
//(디폴트 매개 변수의 기본 문법) void a(int i = 0) {
std::cout << i << std::endl;
}
//함수 1번
//void a() {
std::cout << 1 << std::endl;
}
//함수 2번
//void a(int d) {
std::cout << d*10 << std::endl;
}
//함수 3번
void b(int i = 0) {
std::cout << i << std::endl;
}
void c(int a = 0, int b = 0, int c = 0) {
std::cout << a + b + c << std::endl;
}
//디폴트 매개변수는 마지막 인자부터 써야한다.
//void d(int a = 0, int b, int c) {
std::cout << a + b + c << std::endl;
}
//void d(int a = 0, int b , int c = 0) {
std::cout << a + b + c << std::endl;
}
//함수의 원형과 정의를 분리했을 경우 사용 전에 매개변수가 나타나야 한다.
void d(int a, int b, int c);
void d(int a = 0, int b = 0, int c = 0) {
std::cout << a + b + c << std::endl;
}
//디폴트 매개변수를 사용할 경우 함수의 원형이 main의 뒤에 있어서는 안된다.
void e(int a, int b, int c);
int main() {
/*
a(); //함수 1번과 2번 중 어떤 것을 호출하는지 애매하다.
a(1); //함수 1번과 3번 중 어떤 것을 호출하는지 애매하다.
*/
b(10); //b함수를 인수 주고 호출.
b(); //b함수를 인수 없이 호출.
//매개변수는 마지막 값부터 생략된다. 즉, 디폴트 매개 변수도 마지막 값부터 줄 수 있다.
c(1, 2, 3); c(1, 2); c(1); c(); //됨
d(); //이건 안됨.
//e(); }
void e(int a = 0, int b = 0, int c = 0) {
std::cout << a + b + c << std::endl;
}
8. 'inline'키워드가 추가되었다. 함수 호출문이 함수 본문으로 아예 치환되는 함수를 말한다.
◆ 매크로 함수와의 차이점
1) 매크로 함수는 전처리기에 의해서 컴파일 전에 치환되고, 인라인 함수는 컴파일 과정에서 치환이 이루어진다.
2) 매크로 함수는 전처리기에 의한 기계적인 대치라서 잘못 사용될 수 있다.
3) 매크로 함수는 인수의 타입에 상관없이 작동하지만, 인라인 함수는 정해진 타입의 인수만을 받을 수 있다.
물론 이외에도 모던C++에 추가된 것들까지 생각하면 정말 수많은 것이 다르다.
이제는 굳이 C언어를 배우고 C++를 배우기보다는 바로 C++을 배우는 것을 추천한다.