Подтвердить что ты не робот

Разница между std:: function <> и стандартным указателем функции?

В чем разница между std:: function < > и стандартным указателем функции?

то есть:

typedef std::function<int(int)> FUNCTION;
typedef int (*fn)(int);

Действительно ли они одинаковы?

4b9b3361

Ответ 1

Указатель функции - это адрес фактической функции, определенной в С++. std::function - это оболочка, которая может содержать любой тип вызываемого объекта (объекты, которые могут использоваться как функции).

struct FooFunctor
{
    void operator()(int i) {
        std::cout << i;
    }
};

// Since `FooFunctor` defines `operator()`, it can be used as a function
FooFunctor func;
std::function<void (int)> f(func);

Здесь std::function позволяет абстрагироваться от того, какой именно вызываемый объект вы имеете дело с — вы не знаете его FooFunctor, вы просто знаете, что он возвращает void и имеет один параметр int.

Реальный пример, когда эта абстракция полезна, - это когда вы используете С++ вместе с другим языком сценариев. Возможно, вы захотите создать интерфейс, который может совместно использовать обе функции, определенные в С++, а также функции, определенные на языке сценариев.

Изменить: Связывание

Наряду с std::function вы также найдете std::bind. Эти два являются очень мощными инструментами при совместном использовании.

void func(int a, int b) {
    // Do something important
}

// Consider the case when you want one of the parameters of `func` to be fixed
// You can used `std::bind` to set a fixed value for a parameter; `bind` will
// return a function-like object that you can place inside of `std::function`.

std::function<void (int)> f = std::bind(func, _1, 5); 

В этом примере объект функции, возвращаемый bind, принимает первый параметр _1 и передает его в func в качестве параметра a и устанавливает b как константу 5.

Ответ 2

Они совсем не то же самое. std::function - сложный, тяжелый, сдержанный, почти магический тип, который может содержать любой вызываемый объект, а указатель функции - просто простой указатель. Если вам это удастся, вы должны выбрать либо голой указатель функции, либо auto - bind/auto -lambda. Используйте только std::function, если вам действительно нужен систематический способ организации гетерогенной коллекции вызываемых объектов, таких как функции, функторы, захват lambdas и выражения bind.


Обновление: Немного о типах auto: Сравните следующие две функции:

void do_something_1(std::function<void(int)> f, int a) { f(a); }

template <typename F, typename A> void do_something_2(F f, A a) { f(a); }

Теперь представьте, что вы вызываете их с помощью выражения лямбда или bind:

do_something_X([foo, &bar](int n){ bar += n*foo; },     12);
do_something_X(std::bind(X::bob, &jim, true, _1, Blue), 13);

Вторая версия с шаблоном более эффективна, поскольку в обоих случаях аргумент F выводится на фактический, непознаваемый тип выражения. Первая версия с std::function не является шаблоном и может выглядеть более простым и преднамеренным, но она всегда создает конструкцию объекта std::function и, возможно, переносит затраты на стирание и виртуальную доставку нескольких типов.

Ответ 3

A std::function имеет состояние. Он может содержать дополнительные параметры, связанные с ним.

Эти параметры могут варьироваться от таких вещей, как другие классы, другие функции или даже эти указатели на вызовы функций-членов.

Указатель функции замены не typedef int (*fn)(int);

Это typedef int (*fn)(void*,int);, при этом void* регенерирует состояние, которое будет скрыто в std::function.

Ответ 4

Нет.

Один - это указатель на функцию; другой - объект, который служит в качестве обертки вокруг указателя функции.

Они в значительной степени представляют одно и то же, но std::function намного мощнее, что позволяет делать привязки и многое другое.