본문 바로가기
프로그래밍/C++

[C++] 11. C++의 "고급 주제(기타)"

by iwbap 2024. 6. 17.
728x90

C++ 학습: 고급 주제

C++는 다양한 고급 기능을 통해 복잡한 프로그램을 효율적으로 작성할 수 있도록 합니다. 이번 글에서는 전처리기 지시자, 네임스페이스, 다중 스레딩, 그리고 최신 C++ 표준의 새로운 기능들에 대해 알아보겠습니다.


1. 전처리기 지시자: #define, #include, #if 등

전처리기 지시자는 컴파일러가 소스 코드를 컴파일하기 전에 처리해야 할 명령을 지정합니다. 주요 전처리기 지시자는 다음과 같습니다.

 

  • #define : 매크로를 정의합니다.
[cpp]
 
#define PI 3.14159
#define SQUARE(x) ((x) * (x))

#include <iostream>
using namespace std;

int main() {
    cout << "PI: " << PI << endl;
    cout << "SQUARE(5): " << SQUARE(5) << endl;
    return 0;
}
 
 
  • #include : 다른 파일을 포함합니다.
[cpp]
 
#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> vec = {1, 2, 3, 4, 5};
    for (int i : vec) {
        cout << i << " ";
    }
    cout << endl;
    return 0;
}
 
 
  • #if, #elif, #else, #endif : 조건부 컴파일을 수행합니다.
[cpp]
 
#include <iostream>
using namespace std;

#define DEBUG

int main() {
    #ifdef DEBUG
    cout << "Debug mode is ON" << endl;
    #else
    cout << "Debug mode is OFF" << endl;
    #endif
    return 0;
}
 

위의 예제에서 #define은 상수와 매크로를 정의하고, #include는 필요한 헤더 파일을 포함하며, #if 계열의 지시자는 조건부로 코드를 컴파일할 수 있도록 합니다.


2. 네임스페이스: 네임스페이스의 정의와 사용

네임스페이스는 이름 충돌을 방지하고 코드의 가독성을 높이기 위해 사용됩니다. 네임스페이스를 정의하고 사용하는 방법은 다음과 같습니다.

 

- 네임스페이스 정의와 사용 예제

[cpp]
 
#include <iostream>

namespace MyNamespace {
    void myFunction() {
        std::cout << "Hello from MyNamespace!" << std::endl;
    }
}

int main() {
    MyNamespace::myFunction(); // 네임스페이스를 사용하여 함수 호출
    return 0;
}
 

위의 예제에서 MyNamespace 네임스페이스는 myFunction 함수를 정의하고, main 함수에서 이를 호출합니다.

 

 

- 네임스페이스를 사용하여 이름 충돌 방지

[cpp]
 
#include <iostream>

namespace FirstNamespace {
    void display() {
        std::cout << "This is FirstNamespace" << std::endl;
    }
}

namespace SecondNamespace {
    void display() {
        std::cout << "This is SecondNamespace" << std::endl;
    }
}

int main() {
    FirstNamespace::display(); // FirstNamespace의 display 함수 호출
    SecondNamespace::display(); // SecondNamespace의 display 함수 호출
    return 0;
}
 

위의 예제에서 두 개의 네임스페이스 FirstNamespace와 SecondNamespace는 각각 display 함수를 정의하고, 이름 충돌 없이 독립적으로 사용할 수 있습니다.


3. 다중 스레딩: C++11의 std::thread

다중 스레딩은 여러 스레드를 사용하여 동시에 여러 작업을 수행하는 기능입니다. C++11에서는 std::thread를 통해 다중 스레딩을 지원합니다.

 

- 다중 스레딩 예제

[cpp]
 
#include <iostream>
#include <thread>

void printHello() {
    std::cout << "Hello from thread!" << std::endl;
}

int main() {
    std::thread t1(printHello); // 스레드 생성
    t1.join(); // 스레드가 종료될 때까지 대기

    std::thread t2([]() {
        std::cout << "Hello from lambda thread!" << std::endl;
    });
    t2.join();

    return 0;
}
 

위의 예제에서 std::thread를 사용하여 두 개의 스레드를 생성하고, 각각의 스레드에서 함수를 실행합니다. join 함수를 사용하여 스레드가 종료될 때까지 대기합니다.

 

 

- 다중 스레딩에서 데이터 공유

[cpp]
 
#include <iostream>
#include <thread>
#include <vector>

void accumulateSum(int& sum, const std::vector<int>& nums) {
    for (int num : nums) {
        sum += num;
    }
}

int main() {
    std::vector<int> nums = {1, 2, 3, 4, 5};
    int sum = 0;

    std::thread t(accumulateSum, std::ref(sum), std::ref(nums)); // 스레드 생성
    t.join(); // 스레드가 종료될 때까지 대기

    std::cout << "Sum: " << sum << std::endl;

    return 0;
}
 

위의 예제에서 std::ref를 사용하여 sum 변수와 nums 벡터를 스레드 함수에 참조로 전달합니다.


4. C++11, C++14, C++17, C++20의 새로운 기능: 최신 C++ 표준의 새로운 기능들

C++의 최신 표준(C++11, C++14, C++17, C++20)은 다양한 새로운 기능을 도입하여 언어의 표현력과 성능을 향상시켰습니다. 주요 기능들은 다음과 같습니다:

 

1. C++11

 

- 자동 타입 추론(auto)

[cpp]
auto x = 10; // x는 int 타입
auto y = 3.14; // y는 double 타입
 

- 범위 기반 for 루프

[cpp]
#include <vector>
#include <iostream>
using namespace std;

int main() {
    vector<int> vec = {1, 2, 3, 4, 5};
    for (auto i : vec) {
        cout << i << " ";
    }
    cout << endl;
    return 0;
}
 

- 스마트 포인터(unique_ptr, shared_ptr)

[cpp]
#include <memory>
#include <iostream>
using namespace std;

int main() {
    unique_ptr<int> ptr1 = make_unique<int>(10);
    cout << *ptr1 << endl;

    shared_ptr<int> ptr2 = make_shared<int>(20);
    cout << *ptr2 << endl;

    return 0;
}

 

 

2. C++14

 

- 제네릭 람다

[cpp]
 
auto lambda = [](auto x, auto y) { return x + y; };
cout << lambda(2, 3) << endl; // 5
cout << lambda(2.5, 3.5) << endl; // 6.0
 
 
 

3. C++17

 

- 구조화된 바인딩

[cpp]
#include <tuple>
#include <iostream>
using namespace std;

int main() {
    tuple<int, double, string> t(1, 2.3, "tuple");
    auto [a, b, c] = t;
    cout << a << " " << b << " " << c << endl;

    return 0;
}
 

- if 초기화문

[cpp]
#include <iostream>
using namespace std;

int main() {
    if (int x = 10; x > 5) {
        cout << "x is greater than 5" << endl;
    }

    return 0;
}
 
 

4. C++20

 

- 코루틴

[cpp]
#include <iostream>
#include <coroutine>

struct ReturnObject {
    struct promise_type {
        ReturnObject get_return_object() { return {}; }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        void unhandled_exception() {}
    };
};

ReturnObject counter() {
    for (int i = 0; i < 3; ++i) {
        std::cout << i << std::endl;
        co_await std::suspend_always{};
    }
}

int main() {
    auto h = counter();
    return 0;
}
 

- 개념(concepts)

[cpp]
#include <iostream>
#include <concepts>

template <typename T>
concept Integral = std::is_integral_v<T>;

template <Integral T>
T add(T a, T b) {
    return a + b;
}

int main() {
    std::cout << add(2, 3) << std::endl;
    // std::cout << add(2.0, 3.0) << std::endl; // 오류: double은 Integral이 아님
    return 0;
}
 

위의 예제들은 최신 C++ 표준의 주요 기능들을 보여줍니다. 이러한 기능들은 코드의 표현력을 높이고, 더 안전하고 효율적인 프로그램을 작성하는 데 도움을 줍니다.


이번 글에서는 C++의 고급 주제에 대해 알아보았습니다. 전처리기 지시자, 네임스페이스, 다중 스레딩, 그리고 최신 C++ 표준의 새로운 기능들을 이해하고 활용하면 복잡한 프로그램을 더 효율적으로 작성할 수 있습니다. 다음 단계에서는 실습과 프로젝트를 통해 이러한 기능들을 실제로 적용해보세요. Happy Coding!

728x90