1. 람다함수와 std::function, std::bind, for_each

1) 람다함수

  • 람다함수: 이름 없이 선언되고 사용할 수 있는 함수 리터럴
[](const int& i) -> void {cout << "Hello, World" << endl;} (1234);

2) std::function

  • 함수 래퍼
 std::function<void()> printHello = []() { std::cout << "Hello, World\n"; };
 printHello();

3) std::bind

  • 함수 바인딩
auto boundFunc = std::bind(printHello);
boundFunc();

placeholder

Object instance;
auto f = std::bind(&Object::hello, &instance, std::placeholders::_1);
  • 파라미터의 개수를 딱 잡아준다.

4) for_each

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

    // for_each와 람다를 사용하여 벡터의 각 요소를 출력
    std::for_each(vec.begin(), vec.end(), [](int i) {
        std::cout << i << ' ';
    });
    std::cout << std::endl;
    
    return 0;
}

2. C++ 17 함수에서 여러 개의 리턴 값 반환하기

  • 아래 처럼 작성하면 여러값을 반환할 수 있다.
#include <tuple>
#include <iostream>

std::tuple<int, double, std::string> getValues() {
    return std::make_tuple(1, 2.3, "Hello");
}

int main() {
    auto [i, d, s] = getValues();
    std::cout << i << ", " << d << ", " << s << std::endl;
    return 0;
}

3. std::thread와 멀티쓰레딩 기초

멀티쓰레딩
프로세스: 실행 중인 프로그램의 인스턴스
쓰레드: 프로세스 내에서 실행되는 흐름의 단위
멀티쓰레딩: 하나의 프로세스가 여러 쓰레드를 동시에 실행하여 여러 작업을 동시에 처리할 수 있는 기법
멀티쓰래딩은 직접 구현해야한다.

#include <iostream>
#include <thread>
#include <chrono>
#include <vector>
#include <mutex>

using namespace std;

int main(){
	const int num_pro = std::thread::hardware_concurrency(); // 컴퓨터의 코어 갯수 확인
    cout << std::this_thread::get_id() << endl; // 해당 작업의 쓰레드의 아이디
    
    std::thead t1 = std::thread([]() {while (true) {}}); 
    
    t1.join(); // t1이 끝날 때 까지 기다림
}
  • 멀티쓰레딩의 개수와 하드웨어의 프로세스 개수를 맞추는 것이 일반적
  • 하지만 항상 예외는 존재

4. 레이스 컨디션, std::atomic, std::scoped_lock

레이스 컨디션: 두 개 이상의 스레드가 동시에 공유 자원에 접근하려고 할 때 발생하는 문제
atomic: 여러 스레드에서 동시에 접근할 수 있는 변수를 안전하게 사용
scoped_lock: 블록 범위 내에서 뮤텍스를 안전하게 잠그고, 범위를 벗어날 때 자동으로 뮤텍스를 해제

#include <iostream>
#include <atomic>
#include <thread>
#include <mutex>

std::atomic<int> counter(0);
std::mutex mtx;

void incrementCounter() {
    counter++;
    std::scoped_lock lock(mtx);
    // 여기서 안전하게 공유 자원에 접근
}

int main() {
    std::thread t1(incrementCounter);
    std::thread t2(incrementCounter);

    t1.join();
    t2.join();

    std::cout << counter << std::endl;
    return 0;
}

5. 작업 기반 비동기 프로그래밍

비동기 프로그래밍이란?
여러 작업을 동시에 실행하면서, 현재 스레드의 실행을 차단하지 않고 결과를 기다리는 프로그래밍 방식. 효율적으로 시스템 리소스를 활용하고 애플리케이션의 응답성을 향상시킬 수 있음.

#include <iostream>
#include <future>
#include <thread>

using namespace std;

int main() {
	// mutli-threading
    {
    	int result;
        // 별도의 스레드를 생성하여 람다 함수를 실행
        std::thread t([&] {result = 1 + 2;});
        t.join(); // t 스레드가 종료될 때까지 기다림
        cout << result << endl; // 결과 출력
    }
    
    //task-based parallelism
    {
    	// std::async를 사용하여 비동기적으로 람다 함수를 실행
    	auto fut = std::async([] {return 1 + 2; });
        cout << fut.get() << endl; // 결과가 준비될 때까지 기다린 후 결과 출력
    }
}
  • 일반적으로 thread보다 async를 더 선호한다.
//future and promise
{
	std::promise<int> prom;
    auto fut = prom.get_future();
    
    auto t = std::thread([](std::promise<int>&& prom)
    {
    	prom.set_value(1+2);
    }, stdd::moce(prom));
    
    cout << fut.get() endl;
    t.join();
}

6. 멀티쓰레딩 에제(백터 내적)


아래 링크
https://velog.io/@ehgus8621/%EB%A9%80%ED%8B%B0%EC%93%B0%EB%A0%88%EB%94%A9-%EB%B0%B1%ED%84%B0%EB%82%B4%EC%A0%81-%EC%98%88%EC%8B%9C-%EC%BD%94%EB%93%9C%ED%99%8D%EC%A0%95%EB%AA%A8%EC%9D%98-TBCPP

7. 완벽한 전달과 std::forward

  • l-value와 r-value가 있는 fucn는 template에 의해 타입이 사라진다
  • 이를 살려주는 것이 forward
teplate<typename T>
void func_wrapper(T&& t){
	func(std::forward<T>(t));
}

8. 자료형 추론 auto와 decltype

1) auto

  • auto: 긴타입을 간결하게 줄여줌
  • const, &, volatile은 읽지 않는다.
  • 다만 대입된것이 포인터일 경우 const, *까지 다 읽는다
  • auth& 는 const를 읽는다.
  • auto&&: R-value, 대입에 따라 밸류를 결정
  • 람다함수는 파라미넡에 auto를 사용가능

2) decltype

  • decltype: auto가 컴파일타임에서 타입을 추론하기에 역부족일 때 주로 사용

  • 새로운 데이터 타입을 정의

    typedef decltype(A) B or declytype(A) B = A;

  • decltype은 *, const 등등을 그대로 보존

  • 반환 가능 , 함수 이름 뒤에 '-> 리턴 타입'

  • decltype((A))은 래퍼런스 & 를 타입에 덧 붙여줌

  • A가 연산 식이라면

    A의 연산 결과가 변수라면 &를 붙임
    연산 결과가 R-value라면 &를 붙이지 않는다.
    A 연산식에 사용된 두 변수가 같은 데이터 타입이라면 결과 데이터 타입에 &을 타입에 덧붙여 준다.
    A 연산식에 사용된 두 변수가 다른 데이터 타입이라면 결과 데이터 타입에 &을 타입에 덧붙여주지 않는다.

  • std::remove_reference를 사용하여 &를 제거할 수 있따.

  • 런타입이 아닌 컴파일 타임에 결정된다.

profile
좋은 지식 나누어요

0개의 댓글

Powered by GraphCDN, the GraphQL CDN