함수 포인터
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
함수 포인터는 실행 가능한 메모리 내 함수의 메모리 주소를 저장하는 변수로, 이를 통해 함수를 간접적으로 호출할 수 있게 해준다. C 언어에서 함수 포인터는 다른 함수의 인자로 전달하거나 런타임에 함수의 동작을 변경하는 데 사용되며, C++에서도 함수를 다른 함수로 전달하기 위해 활용된다. C++에서는 멤버 함수를 가리키는 포인터, 함수 객체(functor), 람다 표현식 등 다양한 방식으로 함수를 처리하며, 컴파일러 최적화를 위해 람다 표현식이나 함수 객체를 선호하는 경향이 있다.
더 읽어볼만한 페이지
- 함수 (프로그래밍) - 사용자 정의 함수
사용자 정의 함수는 프로그래밍 언어와 데이터베이스 시스템에서 사용자가 직접 정의하여 재사용할 수 있는 코드 블록이다. - 함수 (프로그래밍) - 코루틴
코루틴은 실행을 멈췄다가 다시 시작할 수 있는 서브루틴의 특별한 형태로, 로컬 데이터를 보존하며 다양한 방식으로 구현되고 여러 프로그래밍 상황에서 유용하게 쓰인다. - 자료형 - 참조
참조는 프로그래밍에서 메모리 주소나 다른 데이터를 가리키는 값으로, 데이터의 효율적인 전달과 공유를 위해 사용되며, 포인터, 파일 핸들, URL 등이 그 예시이다. - 자료형 - 익명 함수
익명 함수는 이름이 없는 함수로, 람다 추상, 람다 함수, 람다 표현식, 화살표 함수 등으로 불리며, 함수형 프로그래밍 언어에서 람다식 형태로 많이 사용되고 고차 함수의 인수, 클로저, 커링 등에 활용되지만, 재귀 호출의 어려움이나 기능 제한과 같은 단점도 존재한다.
| 함수 포인터 |
|---|
2. 간단한 함수 포인터
함수(또는 서브루틴) 포인터의 가장 간단한 구현은 실행 가능한 메모리 내에서 함수의 메모리 주소를 포함하는 변수로 구현된다.[3] PL/I, COBOL과 같은 구세대 3세대 언어, 그리고 파스칼과 C와 같은 현대적인 언어에서 일반적으로 이러한 방식으로 함수 포인터를 구현한다.[3] C의 경우 일반적으로 이 방식으로 함수 포인터를 구현하는데, 현대 언어들보다는 타입이 안전하지 않다. 현대 언어들은 함수의 반환 값의 자료형과 함수에 대한 매개변수의 자료형 정보처럼, 함수 포인터 변수와 자료형 정보가 더 관련있기 때문이다.[11]
2. 1. C 예제
C 언어에서 함수 포인터는 함수의 주소를 저장하고, 이를 통해 함수를 간접적으로 호출하는 데 사용된다. 다음은 함수 포인터의 사용 예시이다.```c
#include
#include
double cm_to_inches(double cm) {
return cm / 2.54;
}
int main(void) {
double (*func1)(double) = cm_to_inches;
char * (*func2)(const char *, int) = strchr;
printf("%f %s", func1(15.0), func2("Wikipedia", 'p'));
/* prints "5.905512 pedia" */
return 0;
}
```
위 코드는 함수 포인터의 두 가지 사용을 보여준다.
- `func1`은 `double`형 매개변수 하나를 가지며 다른 `double`형을 반환하고, 센티미터를 인치로 변환한다.
- `func2`는 정수형과 상수 문자 배열에 대한 포인터를 가지며 문자 포인터를 반환하고, 문자열에서 주어진 문자의 첫 번째 발생에 대한 포인터를 반환하는 문자열 라이브러리 함수의 역할을 한다.
```c
#include
#include
// 함수 포인터를 인수로 받는 함수
double compute_sum(double (*funcp)(double), double lo, double hi)
{
double sum = 0.0;
// 가리키는 함수 '*funcp'가 반환한 값 추가
for (int i = 0; i <= 100; i++)
{
double x, y;
// 함수 포인터 'funcp'를 사용하여 함수 호출
x = i / 100.0 * (hi - lo) + lo;
y = (*funcp)(x);
sum += y;
}
return sum / 101.0;
}
int main(void)
{
double (*fp)(double); // 함수 포인터
double sum;
// 'sin()'을 가리키는 함수로 사용
fp = sin;
sum = compute_sum(fp, 0.0, 1.0);
printf("sum(sin): %f\n", sum);
// 'cos()'을 가리키는 함수로 사용
fp = cos;
sum = compute_sum(fp, 0.0, 1.0);
printf("sum(cos): %f\n", sum);
return 0;
}
```
위 코드는 리만 적분을 계산하는 `compute_sum` 함수에 `sin`, `cos` 함수를 함수 포인터를 이용하여 전달하는 예시이다. `compute_sum`함수는 함수 포인터 `funcp`를 여러 번 역참조하여, 작동된 함수의 결과들을 더하고 결과인 sum을 반환한다.
```c
#include
static int my_function(int a) {
printf("my_function: %d\n", a);
return 2 * a + 3;
}
int main(void) {
int (*func_ptr)(int a) = my_function;
/* 또는 다음도 가능 */
/*
int (*func_ptr)(int) = &my_function;
- /
int x;
x = (*func_ptr)(10);
/* 또는 다음도 가능 */
/*
x = func_ptr(10);
- /
printf("main: %d\n", x);
return 0;
}
```
위 코드는 함수 포인터 `func_ptr`를 선언하고 `my_function`함수의 주소를 할당하고, `func_ptr`를 통해 함수를 호출하는 방법을 보여준다. C에서는 `fp(arg)` 구문도 허용된다.[7]
```c
#include
static void my_function(int a) {
printf("my_function: %d\n", a);
}
static void caller(void (*func_ptr)(int a), int p) {
(*func_ptr)(p);
}
int main(void) {
caller(my_function, 10);
return 0;
}
```
위 코드는 함수 포인터를 인자로 다른 함수에 전달하는 방법을 보여준다. 함수 `caller`는 인자로 함수 포인터와 정수 값 하나를 받는다. 인자로 받은 정수 값은 해당 함수 포인터를 통해 함수를 호출할 때 전달할 인자로 사용된다.
```c
#include
#include
#define PI 3.14159265358979323846
typedef double (*fx_ptr_t)(double x);
/* 또는 다음도 가능 */
/*
typedef double fx_t(double x);
typedef fx_t* fx_ptr_t;
- /
double integ(double a, double b, fx_ptr_t fp) {
double sum = 0.0;
double x;
int n;
/* 적분 {a,b} f(x) dx 계산 */
for (n = 0; n <= 100; ++n) {
x = (n / 100.0) * (b - a) + a;
sum += (*fp)(x) * (b - a) / (100.0 + 1.0);
}
return sum;
}
int main(void) {
int i;
struct pair {
fx_ptr_t fp;
const char* name;
} pairs[3] = {
{ cos, "cos" },
{ sin, "sin" },
{ tan, "tan" },
};
printf("From 0 to pi/4:\n");
for (i = 0; i < 3; ++i) {
printf("\t" "Integral of %s = %g\n", pairs[i].name, integ(0, PI/4, pairs[i].fp));
}
return 0;
}
```
위 코드는 함수 포인터를 사용하여, 지정된 구간에서 적분값을 계산하는 예시이다. 함수 포인터를 정의할 때는 미리 typedef를 사용하여 함수형 또는 함수 포인터형의 별칭을 정의하는 것이 편리하다.
함수 포인터를 인자로 전달하면, 처리를 외부에서 통합(사용자 정의)할 수 있다. 인자로 전달되는 함수는 '''콜백 함수'''라고도 불린다. 주로 이벤트 처리나, 판단을 외부에 맡겨서 처리를 수행할 때 등에 사용된다.
3. 기능자 (Functor)
기능자(함수 객체)는 함수 호출 연산자(`operator()`)를 구현하는 클래스 타입의 객체로, 함수처럼 동작한다. 기능자는 함수 포인터와 유사하게 사용될 수 있지만, 자체 데이터 값을 가질 수 있어 프로그래머가 클로저를 흉내 낼 수 있게 한다는 점에서 더 강력하다.[12] 멤버 함수를 콜백 함수로 사용해야 할 때도 사용될 수 있다.[12]
많은 "순수" 객체 지향 언어는 함수 포인터를 지원하지 않는다. 하지만 단일 멤버 함수를 정의하는 인터페이스에 대한 참조를 사용해서 비슷한 기능을 구현할 수 있다. C#과 비주얼 베이직 닷넷 같은 언어들은 위임(delegate)을 통해 타입이 안전한 함수 포인터를 구현한다.
일급 함수를 지원하는 언어에서는 함수를 데이터처럼 취급하여 다른 함수에 전달, 반환하거나 동적으로 생성할 수 있으므로 함수 포인터가 필요하지 않다.
4. 메소드 포인터
C++는 객체 지향 프로그래밍을 지원하므로 클래스는 메서드(멤버 함수)를 가질 수 있다. 정적이 아닌 멤버 함수(인스턴스 메서드)는 암묵적인 매개변수(''this'' 포인터)를 가지는데, 이는 해당 객체가 작동하는 객체를 가리키는 포인터이므로 객체의 타입은 함수 포인터 타입의 일부로 포함되어야 한다. 메서드는 "멤버에 대한 포인터" 연산자인 `.*` 또는 `->*`를 사용하여 해당 클래스의 객체에서 사용된다.[8]
C와 C++에서 함수 포인터는 간단한 주소로 구현될 수 있지만, C++에서 멤버 포인터는 가상 메서드 및 가상 상속을 처리하기 위해 "뚱뚱한 포인터"로 구현되기도 하며, 일반적으로 단순 함수 포인터의 두세 배 크기이다.[8]
C++에서 다음 함수에 대한 포인터는 C의 함수에 대한 포인터와 호환되며, 호출 규약이 동일하다면 직접적인 상호 운용이 가능하다.[8]
- 클래스에 속하지 않는 네임스페이스 레벨의 전역 함수(자유 함수)
- 클래스의 정적 멤버 함수
반면에 클래스의 비정적 멤버 함수에 대한 포인터는 호환되지 않는다. 비정적 멤버 함수에 대한 포인터를 경유한 함수 호출에는 해당 클래스의 인스턴스가 필요하다.[8]
C++에서는 함수에 대한 참조를 정의할 수도 있지만, 비정적 멤버 함수에 대한 참조는 정의할 수 없다.[8]
```c++
#include
void GlobalFunc1() { puts("GlobalFunc1"); }
class MyClass {
public:
static void ClassFunc1() { puts("MyClass::ClassFunc1"); }
void InstanceFunc1() { puts("MyClass::InstanceFunc1"); }
};
int main() {
void(*fpGlobalFunc1a)() = GlobalFunc1;
void(*fpGlobalFunc1b)() = &GlobalFunc1;
void(&frGlobalFunc1)() = GlobalFunc1;
void(*fpClassFunc1a)() = MyClass::ClassFunc1;
void(*fpClassFunc1b)() = &MyClass::ClassFunc1;
void(&frClassFunc1)() = MyClass::ClassFunc1;
fpGlobalFunc1a();
fpGlobalFunc1b();
frGlobalFunc1();
(*fpGlobalFunc1a)();
(*fpGlobalFunc1b)();
(*frGlobalFunc1)();
fpClassFunc1a();
fpClassFunc1b();
frClassFunc1();
(*fpClassFunc1a)();
(*fpClassFunc1b)();
(*frClassFunc1)();
void(MyClass::*fpInstanceFunc1)() = &MyClass::InstanceFunc1;
MyClass obj;
(obj.*fpInstanceFunc1)();
return 0;
}
```
C++에서는 함수 템플릿의 술어(predicate)로 통상 함수 객체(functor) 또는 람다 표현식이 전달되지만, 함수 포인터를 전달할 수도 있다. 단, 함수 객체나 람다 표현식이 컴파일러 최적화에 의한 인라인화가 기대되므로 선호된다. 람다 표현식은 C++11 이후에 표준화된 기능이지만, Boost C++ 라이브러리의 Boost.Lambda를 이용하여 C++03 이전에도 람다 표현식을 사용할 수 있다.[8]
```c++
#include
#include
#include
bool CompareFuncGreater(const int& a, const int& b) {
return a > b;
}
void PrintLine(int x) {
std::cout << x << std::endl;
}
int main() {
// 내림차순으로 정렬.
std::vector
#if 0
std::sort(data.begin(), data.end(), std::greater
std::for_each(data.begin(), data.end(), [](int x) { std::cout << x << std::endl; });
#else
std::sort(data.begin(), data.end(), CompareFuncGreater);
std::for_each(data.begin(), data.end(), PrintLine);
#endif
return 0;
}
```
C++11 이후에는 typedef 대신 using을 사용할 수도 있다. typedef보다 using이 조금 더 이해하기 쉬운 구문이다.[8]
```c++
typedef double (*fx_ptr_t)(double x);
```
다음은 위의 구문 설탕이다.
```c++
using fx_ptr_t = double (*)(double x);
5. C++에서
C++에서는 함수 포인터를 사용하여 함수를 다른 함수에 인수로 전달할 수 있다. C에서는 함수를 가리키는 포인터를 사용하는데, 이는 함수가 역참조되어 전달될 수 없기 때문이다. 다음은 C 스타일 함수 포인터를 이용한 예시이다.
```cpp
// Pointer to functions
#include
using namespace std;
int add(int first, int second)
{
return first + second;
}
int subtract(int first, int second)
{
return first - second;
}
int operation(int first, int second, int (*functocall)(int, int))
{
return (*functocall)(first, second);
}
int main()
{
int a, b;
int (*plus)(int, int) = add;
int (*minus)(int, int) = subtract;
a = operation(7, 5, plus);
b = operation(20, a, minus);
cout << "a = " << a << " and b = " << b << endl;
return 0;
}
```
C++ 표준 라이브러리의 `std::function` 클래스 템플릿을 사용하여 함수 객체를 저장하고 전달할 수도 있다. 다음은 `std::function`을 사용한 예시이다.
```cpp
#include
#include
static double derivative(const std::function
{
double eps2 = eps / 2;
double lo = x0 - eps2;
double hi = x0 + eps2;
return (f(hi) - f(lo)) / eps;
}
static double f(double x)
{
return x * x;
}
int main()
{
double x = 1;
std::cout << "d/dx(x ^ 2) [@ x = " << x << "] = " << derivative(f, x, 1e-5) << std::endl;
return 0;
}
```
C++에서 클래스에 속하지 않는 전역 함수나 클래스의 정적 멤버 함수에 대한 포인터는 C의 함수 포인터와 호환되며, 호출 규약이 동일하다면 직접적인 상호 운용이 가능하다. 반면에 클래스의 비정적 멤버 함수에 대한 포인터는 호환되지 않으며, 호출을 위해서는 해당 클래스의 인스턴스가 필요하다.[8]
C++에서는 함수에 대한 참조를 정의할 수도 있지만, 비정적 멤버 함수에 대한 참조는 정의할 수 없다.[8]
```c++
#include
void GlobalFunc1() { puts("GlobalFunc1"); }
class MyClass {
public:
static void ClassFunc1() { puts("MyClass::ClassFunc1"); }
void InstanceFunc1() { puts("MyClass::InstanceFunc1"); }
};
int main() {
void(*fpGlobalFunc1a)() = GlobalFunc1;
void(*fpGlobalFunc1b)() = &GlobalFunc1;
void(&frGlobalFunc1)() = GlobalFunc1;
void(*fpClassFunc1a)() = MyClass::ClassFunc1;
void(*fpClassFunc1b)() = &MyClass::ClassFunc1;
void(&frClassFunc1)() = MyClass::ClassFunc1;
fpGlobalFunc1a();
fpGlobalFunc1b();
frGlobalFunc1();
(*fpGlobalFunc1a)();
(*fpGlobalFunc1b)();
(*frGlobalFunc1)();
fpClassFunc1a();
fpClassFunc1b();
frClassFunc1();
(*fpClassFunc1a)();
(*fpClassFunc1b)();
(*frClassFunc1)();
void(MyClass::*fpInstanceFunc1)() = &MyClass::InstanceFunc1;
MyClass obj;
(obj.*fpInstanceFunc1)();
return 0;
}
```
C++에서는 함수 템플릿의 술어(predicate)로 함수 객체나 람다 표현식을 전달할 수 있지만, 함수 포인터를 전달하는 것도 가능하다. 컴파일러 최적화를 통한 인라인화가 기대되므로 함수 객체나 람다 표현식이 선호된다. 람다 표현식은 C++11에서 표준화되었으며, Boost C++ 라이브러리의 Boost.Lambda를 이용하면 C++03 이전에도 람다 표현식을 사용할 수 있다.
```c++
#include
#include
#include
bool CompareFuncGreater(const int& a, const int& b) {
return a > b;
}
void PrintLine(int x) {
std::cout << x << std::endl;
}
int main() {
// 내림차순으로 정렬.
std::vector
#if 0
std::sort(data.begin(), data.end(), std::greater
std::for_each(data.begin(), data.end(), [](int x) { std::cout << x << std::endl; });
#else
std::sort(data.begin(), data.end(), CompareFuncGreater);
std::for_each(data.begin(), data.end(), PrintLine);
#endif
return 0;
}
```
C++11 이후에는 `typedef` 대신 `using`을 사용할 수 있다.
```c++
typedef double (*fx_ptr_t)(double x); // typedef 사용
using fx_ptr_t = double (*)(double x); // using 사용
5. 1. C++에서 멤버 함수들에 대한 포인터
C++는 객체 지향적이어서, 클래스는 메소드들을 가질 수 있다. 정적이 아닌 멤버 함수(인스턴스 메소드)들은 암묵적인 매개변수(this 포인터)를 가지는데, 이것은 동작하는 객체를 가리키는 포인터여서, 객체의 타입은 반드시 함수 포인터 타입의 한 부분으로 포함되어야 한다. 그 후 메소드는 연산자 `.*` 또는 `->*` (각각 객체 또는 객체를 가리키는 포인터를 위한)를 사용함으로써 그 클래스의 객체로 사용된다.[8]
C와 C++에서 비록 함수 포인터가 간단한 주소들로 구현될 수 있지만, `sizeof(Fx)==sizeof(void *)` , C++에서 멤버 포인터들은 가상 상속을 다루기 위해서 종종 "뚱뚱한 포인터"로 구현된다(일반적으로 간단한 함수 포인터의 크기에 비해 두세 배).[8]
C++에서 클래스 또는 구조체의 멤버 함수를 다룰 때 함수 포인터를 사용하는 방법은 다음과 같다. 이들은 객체 포인터나 `this` 호출을 사용해서 작동된다. 이들은 타입 안전하다. 정적 멤버 함수를 가리키는 함수 포인터는 `this` 호출이 필요하지 않기 때문에 C 스타일로 만들 수 있다.[8]
```cpp
#include
using namespace std;
class Foo
{
public:
int add(int i, int j)
{
return i+j;
}
int mult(int i, int j)
{
return i*j;
}
static int negate(int i)
{
return -i;
}
};
int bar1(int i, int j, Foo* pFoo, int(Foo::*pfn)(int,int))
{
return (pFoo->*pfn)(i,j);
}
typedef int(Foo::*Foo_pfn)(int,int);
int bar2(int i, int j, Foo* pFoo, Foo_pfn pfn)
{
return (pFoo->*pfn)(i,j);
}
typedef int(*PFN)(int);
int bar3(int i, PFN pfn)
{
return pfn(i);
}
int main()
{
Foo foo;
cout << "Foo::add(2,4) = " << bar1(2,4, &foo, &Foo::add) << endl;
cout << "Foo::mult(3,5) = " << bar2(3,5, &foo, &Foo::mult) << endl;
cout << "Foo::negate(6) = " << bar3(6, &Foo::negate) << endl;
return 0;
}
```
#대안적인 C 및 C++ 구문
6. C/C++ 대안 구문
c
// 'F'는 'char'를 인수로 받아 'int'를 반환하는 함수로 선언됨. 정의는 다른 곳에 있음.
int F(char c);
// 'Fn'은 'char'를 인수로 받아 'int'를 반환하는 함수 형식으로 정의됨.
typedef int Fn(char c);
// 'fn'은 'Fn'에 대한 포인터 형식의 변수로 정의하고, 'F'의 주소를 할당함.
Fn *fn = &F; // '&'는 필수는 아니지만, 무엇을 하고 있는지 강조함.
// 'fn'을 사용하여 'F'를 호출하고, 결과를 변수 'a'에 할당함.
int a = fn('A');
// 'Call'은 'Fn'에 대한 포인터를 인수로 받아 호출하고, 그 결과를 반환하는 함수로 정의됨.
int Call(Fn *fn, char c) {
return fn(c);
} // Call(fn, c)
// 'Call' 함수를 호출하여 'F'를 전달하고, 그 결과를 'call'에 할당함.
int call = Call(&F, 'A'); // 마찬가지로 '&'는 필요하지 않음.
// 레거시: 기존 코드 기반을 유지하기 위해 위의 정의 스타일을 먼저 사용할 수 있음.
// 그런 다음 새 스타일을 사용하여 원래 형식을 정의할 수 있음.
// 'PFn'은 'Fn' 형식에 대한 포인터 형식으로 정의함.
typedef Fn *PFn;
// 'PFn'은 'Fn *'가 사용될 수 있는 모든 곳에서 사용할 수 있음.
PFn pfn = F;
int CallP(PFn fn, char c);
```
위 코드는 `typedef`를 사용하여 함수 포인터를 더 명확하게 정의하고 사용하는 방법을 보여준다. `Fn`은 `char`형 인수를 받고 `int`형을 반환하는 함수 형식을 정의한다. `fn`은 `Fn` 형식의 함수를 가리키는 포인터 변수이다. `Call` 함수는 `Fn` 형식의 함수 포인터를 인수로 받아 해당 함수를 호출한다.
`typedef`를 사용하면 함수 포인터 형식을 간결하게 표현할 수 있으며, 코드 가독성을 높일 수 있다. 또한, 기존 코드와의 호환성을 위해 레거시 스타일(`typedef`와 포인터를 함께 사용하는 방식)도 지원한다.
7. C++ 람다 표현식
C++11부터 도입된 람다 표현식은 함수 객체를 간편하게 생성하는 방법이다.[8] 람다 표현식을 사용하면 함수 포인터 대신 컴파일러 최적화(인라인화)에 유리하다.[8]
```c++
#include
#include
#include
bool CompareFuncGreater(const int& a, const int& b) {
return a > b;
}
void PrintLine(int x) {
std::cout << x << std::endl;
}
int main() {
// 내림차순으로 정렬.
std::vector
#if 0
std::sort(data.begin(), data.end(), std::greater
std::for_each(data.begin(), data.end(), [](int x) { std::cout << x << std::endl; });
#else
std::sort(data.begin(), data.end(), CompareFuncGreater);
std::for_each(data.begin(), data.end(), PrintLine);
#endif
return 0;
}
```
위 예제에서 `#if 0` / `#else` / `#endif` 전처리기를 사용하여 람다 표현식 대신 함수 포인터를 사용하도록 변경할 수 있다. `std::sort()` 함수의 세 번째 인자에 `CompareFuncGreater` 함수 포인터를 전달하고, `std::for_each()` 함수의 세 번째 인자에 `PrintLine` 함수 포인터를 전달한다.
C++에서는 함수 템플릿의 술어(predicate)로 함수 객체나 람다 표현식을 전달하는 것이 일반적이지만, 함수 포인터를 전달할 수도 있다.[8] 그러나 함수 객체나 람다 표현식이 컴파일러 최적화를 통해 인라인화될 가능성이 높아 더 선호된다.[8]
참조
[1]
웹사이트
Fortran Examples
http://www.esm.psu.e[...]
2013-09-14
[2]
웹사이트
The Function Pointer Tutorials
http://www.newty.de/[...]
logo
2011-04-13
[3]
웹사이트
The Function Pointer Tutorials
http://www.newty.de/[...]
logo
2011-04-13
[4]
웹사이트
Expertise: Intermediate Language: C++: Use Functor for Callbacks in C++
http://www.devx.com/[...]
DevX.com
2011-04-13
[5]
Microsoft Docs
既定のマーシャリングの動作
https://docs.microso[...]
[6]
IBM Knowledge Center
左辺値と右辺値
https://www.ibm.com/[...]
[7]
웹사이트
C FAQ 4
http://www.kouno.jp/[...]
2008-10-14
[8]
간행물
ISO/IEC 14882 | 8.3.3 Pointers to members
[9]
웹인용
Fortran Examples
http://www.esm.psu.e[...]
2016-01-21
[10]
웹인용
The Function Pointer Tutorials
http://www.newty.de/[...]
logo
2016-01-21
[11]
웹인용
The Function Pointer Tutorials
http://www.newty.de/[...]
logo
2016-01-21
[12]
웹인용
Expertise: Intermediate Language: C++: Use Functor for Callbacks in C++
http://www.devx.com/[...]
DevX.com
2016-01-21
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com