ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [C++] C와 C++
    C++/이것이 C++이다 2021. 1. 29. 17:18

    C++는 C를 기반으로 만들어졌지만

    절차지향인 C와는 달리, 객체지향의 요소를 도입했습니다.

    또한 C에 '++'가 붙은만큼, C의 여러 요소를 개선, 변경한 부분이 있는데

    이번 글에서는 그러한 변경점 중 간단한 몇 가지를 살펴보도록 하겠습니다.

     


     

    1. 자료형에 대하여

     

    더보기

    C++의 정수형의 int, long

    실수형의 float, double 등, 기본 자료형은 C와 C++, 그 외 다른 프로그래밍 언어와 유사합니다.

    하지만 C++은 C에서 추가된 몇 개의 자료형이 있는데

    bool, auto, decltype 등의 자료형이 바로 그것입니다.

    bool은 true, false의 논리적 참 거짓을 값으로 가질 수 있는 변수

    auto는 컴파일러가 형식을 규정하는 변수

    decltype은 declared type의 약어로, 인자값으로 전달한 변수의 type과 같은 type의 변수입니다.

     

    Examples

    #include <iostream>
    
    void main() { 
    	int typeA = 0;
    	auto typeB = 1;
    	auto typeC = 0.1;
    	auto typeD = 'a';
    	auto typeE = "ABC";
    	bool typeF = false;
    	decltype(typeC) typeG = 1;
    
    	std::cout << typeid(typeA).name() << "\n"
    		<< typeid(typeB).name() << "\n"
    		<< typeid(typeC).name() << "\n"
    		<< typeid(typeD).name() << "\n"
    		<< typeid(typeE).name() << "\n"
    		<< typeid(typeF).name() << "\n"
    		<< typeid(typeG).name() << "\n";
    
    }
        
    int
    int
    double
    char
    char const *
    bool
    double

     

    2. "Hello World!"에 대하여

     

    더보기

    C

    #include <stdio.h>
    
    void main(){
    	printf("Hello World!");
    }

     

    C++

    #include <iostream>
    
    void main(){
    	std::cout << "Hello World!";
    }

    C++의 iostream 헤더에 있는 std::cout 및 std::cin은

    C에서 사용하던 printf, scanf(scanf_s)보다 사용이 직관적입니다.

     

    자세한 내용은 다음 문단에서 살펴보도록 하겠습니다.

     

    3. 입출력에 대하여

     

    더보기

    C와 C++에서 사용하는 입, 출력을 비교해보도록 하겠습니다.

    #include <stdio.h>
    #include <iostream>
    
    void main() {
    	int A;
    	float B;
    	double C;
    
    	// I/O in 'C' style
    
    	scanf("%d", &A);
    	scanf("%f", &B);
    	scanf("%lf", &C);
    	printf("A : %d, B : %f, C : %lf\n", A, B, C);
    
    	// I/O in 'C++' style
    
    	std::cin >> A;
    	std::cin >> B;
    	std::cin >> C;
    	std::cout << "A : " << A << ", B : " << B << ", C : " << C << "\n";
    }

    C++의 cin, cout이 printf, scanf(scanf_s)와 가지는 가장 큰 차이점이라면

    입출력을 객체에 전달하여 사용하는 점 이라고 할 수 있겠습니다.

    printf와 scanf는 입, 출력에 대한 형식 지정자를 일일히 지정해주어야 하지만

    cout과 cin은 형식에 대한 책임을 cout, cin객체에 일임하였습니다.

    그 결과, C의 입출력에 비해서 C++의 std::cout, std::cin은 상대적으로 직관적인 것을 볼 수 있습니다.

    하지만 속도의 측면에서는 그러지 못 했는데, 이 부분은 차후 다른 글에서 다룰 수 있도록 하겠습니다.

     

    4. malloc과 new, free와 delete

     

    더보기

    C에서 메모리의 동적 할당(해제)를 위해 우리는 malloc과 free함수를 사용했습니다.

    (realloc, calloc도 있지만 결론적으로는 동적할당을 위한 함수임은 같으므로 생략합니다.)

    하지만 C++에서는 new와 delete라는 연산자가 추가되어, 내부에서 malloc과 free를 호출합니다.

     

    예제를 살펴보도록 하겠습니다.

    #include <stdio.h>
    
    void main()
    {
    	int* A = (int*)malloc(sizeof(int) * 3);
    
    	A[0] = 1;
    	A[1] = 3;
    	A[2] = 5;
    
    	for (int i = 0; i < 3; i++) {
    		printf("%d\n", A[i]);
    	}
    
    	free(A);
    }
    1
    3
    5

    위와 같은 C style의 동적 할당을, C++에서는 아래와 같이 사용합니다.

     

    #include <iostream>
    
    void main()
    {
    	int* A = new int[3];
    
    	A[0] = 2;
    	A[1] = 4;
    	A[2] = 6;
    
    	for (int i = 0; i < 3; i++) {
    		std::cout << A[i] << "\n";
    	}
    
    	delete[] A;
    }
    2
    4
    6

    위와 같이 동적 배열의 할당에도 이용할 수 있지만,  객체의 동적 할당에도 이용할 수 있습니다.

    또한, new와 delete는 내부적으로 생성자와 소멸자를 호출합니다.

    생성자, 소멸자 등 C++의 객체(클래스)와 관련된 내용은 이 글에 서술하였습니다.

     

    5. 포인터와 참조자

     

    더보기

    C++에 새로 추가된 참조자(Reference)는 구조적으로 포인터와 크게 다르지 않습니다.

    포인터에 대해 설명할 때 많이 볼 수 있는 Swap함수를 예시로 살펴보도록 하겠습니다.

     

    Example (Swap in pointer)

    #include <stdio.h>
    
    void swap(int* a, int* b) {
    	int temp = *a;
    	*a = *b;
    	*b = temp;
    }
    
    void main(){
    	int a = 3;
    	int b = 4;
    	printf("%d %d\n", a, b);
    	swap(&a, &b);
    
    	printf("%d %d\n", a, b);
    }
    3 4
    4 3

    이처럼 포인터를 이용한 Swap함수를, 참조자를 이용하면 아래와 같이 정의할 수 있습니다.

     

    Example (Swap in reference)

    #include <stdio.h>
    
    void swap(int& a, int& b) {
    	int temp = a;
    	a = b;
    	b = temp;
    }
    
    int main()
    {
    	int a = 3;
    	int b = 4;
    	printf("%d %d\n", a, b);
    	swap(a, b);
    
    	printf("%d %d\n", a, b);
    }
    3 4
    4 3

    swap함수 내부에서도, 함수를 호출할때에도 주소와는 관련이 없어보이는 것이 특징이라고 할 수 있습니다.

    참조자를 매개변수로 받는 함수는, 참조하는 객체의 복사본이 아닌 원본을 그대로 "참조" 합니다.

     

    6. 범위 기반 for Loop

     

    더보기

    Range based for loop는 타 언어에 있는 for each 문법과 유사합니다.

    기본적으로 배열의 요소에 접근할 때 매우 용이하게 사용될 수 있습니다.

     

    Example (C style for loop)

    #include <stdio.h>
    
    void main(){
    	int a[5] = {1, 2, 3, 4, 5};
        
    	for(int i=0; i<5; i++){
    		printf("%d ", a[i]);
    	}
    }
    1 2 3 4 5

    위와 같은 방식의 배열 순회는, 배열의 길이가 변경될 경우 for loop의 조건식도 변경해야 하는 문제가 발생할 수 있습니다.

    이러한 문제점을 해결하기 위해, 아래와 같이 범위 기반 for loop를 구성할 수 있습니다.

     

    Example (Range based for loop)

     

    #include <stdio.h>
    
    void main(){
    	int a[5] = {1, 2, 3, 4, 5};
        
    	for(auto i in a){
    		printf("%d ", i);
    	}
        
    	for(auto &i in a){
    		printf("%d ", i);
    	}
    }
    1 2 3 4 5
    1 2 3 4 5

    배열의 길이가 바뀌어도 조건식에 대해 수정이 필요 없다는 점을 확인할 수 있습니다.

    또한, 아래의 범위 기반 for loop는 참조자를 사용하지 않은 것과 사용한 것 두 가지를 모두 사용했는데

    배열의 각 요소에 접근하여, 값에 대한 변경이 필요할 경우 참조자가 필요하다는 것을 설명하고 싶었습니다.

    첫번째 반복문을 통해 배열의 요소를 변경하려고 시도할 경우

    참조자를 사용하지 않았기 때문에, 접근하게 되는 배열의 원소들은 원본이 아닌, 복사본이 됩니다.
    따라서 정상적으로 변경되지 않을 수 있습니다.

     


     

    C를 접한 이후 C++을 공부하는 것이라면

    C와 비교하는 것이 다소 도움이 될 것이라고 생각합니다.

    이후 다루게 될 객체지향 및 다른 문법은 조금 생소할 수 있지만

    기본적으로 C와 공유되는 부분이 많은 것을 볼 수 있었습니다.

     

    읽어주셔서 감사합니다.

    'C++ > 이것이 C++이다' 카테고리의 다른 글

    [C++] 클래스 기본 문법 1  (0) 2021.02.27
    [C++] 클래스를 살펴보기 전에  (0) 2021.02.27
    [C++] 네임스페이스  (0) 2021.02.12
    [C++] 함수 기본  (0) 2021.02.12
    [C++] 이 카테고리에서는  (0) 2021.01.29

    댓글

Designed by Tistory.