함수 포인터 개념부터 std::function까지

 

개념 및 기초

  1. 함수의 시작 번지를 가르키는 포인터 (어셈블리 언어의 호출 스택을 생각해보자)
  2. 포인터 형식 자체가 다르다.
  • 리턴타입(*함수 포인터 이름)(인수목록)
  • 함수 : int Func(int a) => 포인터 : int(*funcPtr)(int)
  • 함수의 시작번지에 들어가기 앞서 인수들의 목록과 리턴 형식(주소) 정보를 (스택에) 저장해야하므로

함수 포인터 사용 방법

  1. 대입 & 호출
  • 대입 : funcPtr = Func; (괄호없이 단독으로 사용된 함수명은 함수의 시작 번지를 나타내는 포인터 상수.)
  • 호출 : 원칙적으로 (*funcPtr)(2); 하지만 컴파일러는 funcPtr(2); 도 동작하게한다.
  • 인자가 잘못 들어가거나 리턴형식을 잘못된 타입으로 받으면 당연히 컴파일 에러, 함수 포인터 형식이 복잡한 이유
  1. 하나의 고유한 타입인 함수 포인터.
  • 원형이 다른 함수 포인터끼리 직접 대입, 복사 불가.
int(*funcPtr1)(int), double(*funcPtr2)(float);
funcPtr1 = funcPtr2; //에러
  • 캐스팅 가능
int(*funcPtr1)(int), double(*funcPtr2)(float);
funcPtr1 = (int(*)(int))funcPtr2;
  1. 응용
  • 함수 포인터 배열
int(*funcPtrArr[MAX_FUNC_NUM])(int); //함수 포인터 변수명 다음에 배열 크기 선언
funcPtrArr[0] = funcPtr1;
  • 함수 포인터의 포인터
int(**funcPPtr)(int); //일단 이건데 불편, 위에도 마찬가지
typedef int(*FUNCPTR)(int); //함수 포인터 타입을 typedef로 정의하고(정의 형식 주의)
FUNCPTR* funcPPtr; //이렇게나
FUNCPTR funcPtr[MAX_FUNC_NUM]; //이렇게 사용하는 것이 가독성이 높다.

함수 포인터의 의미

  1. 함수를 변수로 사용할 수 있다.
  • 하나의 함수포인터만을 가지고 조건에 따라 다른 함수를 실행시킬 수 있다. (fsm에서 활용하는 방법)
  • 함수를 인자로 넘길 수 있다.
  • 함수 포인터 배열이나 구조체를 사용하여 전체 함수그룹을 변경하는 것도 가능하다.
  1. 사용하기 좋은 경우
  • 조건에 따라 선택해야 할 함수가 두 개 이상인 경우. 함수 포인터 배열을 활용하자
  • 함수 선택 분기와 실제 호출 시점이 다른 경우. 미리 선택한뒤 변수에 저장된 함수를 바로 호출하면 된다.
  • 호출할 함수가 외부 모듈(DLL)에 있는 경우, 동적 연결하려면 함수 포인터 사용해야한다.

함수 인자 사용하기

  1. 예제 : 퀵소트
  • 퀵소트 형식
  void qsort(void *base, size_t num, size_t width,
  int ( *compare )(const void *, const void *));
  • compare 함수
 int compare(const void *a, const void *b)
 {
      if (*(int *)a == *(int *)b) return 0;
      if (*(int *)a > *(int *)b) return 1;
      return -1;
 }
  • 실제 퀵소트 호출
int ar[]={34,25,27,19,4,127,9,629,18,7,9,165};
qsort(ar,sizeof(ar)/sizeof(ar[0]),sizeof(int),compare);
for (int i=0;i<sizeof(ar)/sizeof(ar[0]);i++) {
     printf("%d번째 = %d\n",i,ar[i]);
}

클래스 멤버함수의 함수 포인터

  1. 클래스 내부에 있는 메소드, 멤버함수들을 함수 포인터로 사용하고 싶을때.
  2. 기존 C의 함수들은 정적(Static)함수로, 소속이나 사용 인스턴스와 무관하게 사용되었다.
  3. 하지만 클래스의 멤버함수들은 Class 이름을 네임스페이스로 (Class::Function();)
    인스턴스에 의존적으로(this->Function();) 사용되므로 차이가 있다.
  4. 예전 스터디 static부분참조
  5. 실제 코드로 보는 일반/멤버함수 포인터의 차이점과 사용방법 예시
class World
{
 public:
   void Close() {}
   static void Open() {}
};

void foo(){}
int main()
{
   //대입
   void(*fPtr1)() = &foo;            //일반 함수 포인터
   void(*fPtr2)() = &World::Open;    //클래스 멤버 함수 포인터. 
   //클래스의 네임스페이스 설정이 안되어 있으나 static이므로 접근 가능
   void(*fPtr3)() = &World::Close;   //함수 포인터 소속 불명.
   void(World::*fPtr4)() = &World::Close; //함수의 소속을 명시하면 OK

   //호출
   fPtr4();                          //하지만 인스턴스에 바인딩 되지 않으면 에러
   World earth; 
   earth.fPtr4();                   //earth 내부의 멤버함수 fptr4를 찾기때문에 불가능
   (earth.*fPtr4)();                //원칙적 사용방법 이렇게 쓰도록 한다.
}
  1. 결론
  • 멤버함수를 클래스 외부에서 함수 포인터로 선언(사용)할 때 타입에 클래스 소속을 명시해서 써야한다.
  • 멤버함수 호출할때 인스턴스를 참조해서 호출해야한다.

std::function

  1. 일반 함수 포인터의 문제
  • 반환값이 명시적으로 (암시적 형변환 불가) 같은 타입이 아니면 컴파일 에러
  • 오로지 함수만 호환이 가능하다. (functor, 멤버함수 포인터, 람다함수, bind반환값 등 안됨)
  1. std::function을 사용하는 것의 장점
  • 함수 반환값이 암시적 형변환 가능한 타입이면 대입 가능하다.
  • static 함수 포인터 말고도 functor, 멤버함수 포인터, 람다함수, bind반환값 등 위아더월
  • 유연한 사용이 가능하다. (특히 인자로 함수를 받는 경우. 다양한 활용가능)

std::bind

  1. 일련의 인자들을 함수에 바인딩시킨 함수 객체를 반환하는 함수 템플릿
  • std::bind(함수 포인터, 인자...);

  • 예시

      void show_text(const string& t)
     {
         cout << "TEXT: " << t << endl;
     }
     // show_text 함수에 "Bound function"이라는 문자열을 바인딩시킨
     // function<void ()> 타입을 반환한다.
     function <void ()> f = std::bind(show_text, "Bound function");
  1. std::placeHolder를 활용하여 추가 인수 bind
  • bind의 인자 대신 std::placeHolders::_1, _2, _3... _N을 입력
  • 예시

int multiply(int a, int b) { return a * b; }

int main() { // function f 는 multiply 함수에 a 인자는 5로 고정시키고, b 인자는 placeholding만 한다. // 이럼으로써, function f는 하나의 인자(x)를 취하지만, // 그것이 결국 multiply(5, x)의 형태로 함수를 호출하는 것이다.

   auto f = bind(multiply, 5, _1);

   for (int i = 0; i < 10; i++)
   {
       cout << "5 * " << i << " = " << f(i) << endl;
   }
   return 0;

} ```

  1. 클래스 멤버함수의 경우 this를 바인딩해서 쉽게 사용가능
  • reference_wrapper를 사용하여 인스턴스를 참조로 넘겨야 복사가 발생하지 않는다고 한다.(잘 모르겠음)

  • 예시

    BindTest bt;
    auto f2 = bind(&BindTest::MemberFunc, std::ref(bt), _1);
    f2(10);  // bt.MemberFunc(10);

함수 객체 (functor)

  1. 객체를 함수처럼 사용하는 것
  • 객체의 식별자를 함수 이름처럼 : ()연산자를 오버로딩
  • algorithm함수에서 많이 사용된다.
  1. 함수 포인터와 차이점
  • 멤버 변수, 멤버 함수를 가질 수 있다.
  • template 클래스로 범용적으로 사용할 수 있다

 

퍼옴: https://github.com/jwvg0425/ProjectArthas/wiki/%ED%95%A8%EC%88%98-%ED%8F%AC%EC%9D%B8%ED%84%B0-%EA%B0%9C%EB%85%90%EB%B6%80%ED%84%B0-std::function%EA%B9%8C%EC%A7%80

'C++ > C++ 11 14 17' 카테고리의 다른 글

C++ 11 ENUM  (0) 2018.04.11
auto keyword  (0) 2018.04.05
Aggregate and POD  (0) 2018.04.04
R 레퍼런스 타입.  (0) 2017.01.30
Modern C++ [MS]  (0) 2016.12.28


얼마전에 하드 하나를 우연한 기회로 얻었습니다.

그래서 포맷하구 파티션 합치는 도중에 OEM 파티션이라고 있더군요.
삭제도 안되고 ㅠㅠ 왠지 4G 나 차지하는게 꼴붸기 싫고 해서 삭제 방법을 찾아 보았씁니다.



시작해 볼까요?

우선 'Window Key' + 'R' 을 눌러서 '실행' 도구를 커보죠!
윈도우7에서는 시작을 누르고 '프로그램 및 파일 검색' 에 쳐도 됩니다.

그리고 대화 상자에 'Diskpart' 를 치고 확인!! 눌러주세요!



그럼 명령 프롬프트 창이 열립니다.
그리고 현재 본인이 지니고 있는 디스크의 목록이 쫙 표시 됩니다.



여기서는 '디스크 관리 도구'를 사용하여 편집하려는 모든 디스크를 볼수 있습니다. 
본인의 OEM 파티션이 어느 디스크에 위치한 것인지 보시려면 

제어판 → 관리 도구→컴퓨터 관리→저장소→디스크 관리 에서 확인 가능 합니다.
(윈도우7에서는 시작을 누르고 '프로그램 및 파일 검색' 에 '파티션' 이라고 치면 바로 나옴니다. )

전 디스크1에 있더군요. 그럼 'select disk 1' 이라고 쳐보죠.



자~ 디스크 1이 선택되었습니다. 여러분은 자신이 디스크를 선택하세요.
디스크를 선택했으니 디스크 내 파티션을 봐야겠죠? 'list partition' 이라는 명령을 내려봅시다.



파티션 3의 종류가 OEM 이란걸 알았어요~~ 이 자식때문에 이 썡고생을 ㅠ
이 놈을 선택하죠!! 'select partition 3' 이라 명령!!



파티션 3을 선택 했씁니다. 이제 삭제 할꺼에요!!
'delete partition override' 라고 치면 끝!



성공적인 파티션 제거!!   OEM 파티션 안녕~~~~ ㅎㅎ

출처: http://simdoy.tistory.com/90 [ordninary people]

DirectX SDK (June 2010) 을 Windows 7 에 설치하던 중에 Error Code S1023 이 뜹니다.

원인은 최신 버전의 Visual C++ 2010 X86/X64 Redistributable Package 가 설치되어서 발생되는 것입니다.


일단 이것들을 제어판에서 삭제합니다.

DOS 명령어에서 다음과 같이 입력해도 삭제됩니다.

MsiExec.exe /passive /X{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}
MsiExec.exe /passive /X{1D8E6291-B0D5-35EC-8441-6616F567A0F7}


그 다음에 DirectX SDK 를 설치합니다.

http://www.microsoft.com/en-us/download/details.aspx?id=6812


그 다음에 최신 버전의 Visual C++ 2010 X86/X64 Redistributable Package 를 설치합니다.

http://www.microsoft.com/ko-kr/download/details.aspx?id=26999


참고



출처: http://appmaid.tistory.com/11 [App Maid]

+ Recent posts