функциональные объекты по сравнению с указателями функции

У меня есть два вопроса, связанные с функциональными объектами и указателями функции,


Вопрос: 1

Когда я считал различное использование sort алгоритм STL, я вижу, что третий параметр может быть, функциональные объекты, ниже пример

class State {  
  public:  
    //...
    int population() const;  
    float aveTempF() const;  
    //...  
};    
struct PopLess : public std::binary_function<State,State,bool> {  
    bool operator ()( const State &a, const State &b ) const  
        { return popLess( a, b ); }  
};  
sort( union, union+50, PopLess() );  

Вопрос:

Теперь, Как делает оператор, sort(union, union+50,PopLess()) работа? PopLess() должен быть разрешен во что-то как PopLess tempObject.operator() который был бы тем же как выполнение operator () функция на временном объекте. Я вижу это как, передавая возвращаемое значение перегруженной операции т.е. bool (как в моем примере) к sort алгоритм.

Таким образом, Как вид функционирует, разрешают третий параметр в этом случае?


Вопрос: 2

Вопрос

Мы получаем какое-либо конкретное преимущество использования функциональных объектов по сравнению с указателем функции? Если мы будем использовать ниже указателя функции, то он получит какой-либо disavantage?

inline bool popLess( const State &a, const State &b )
    { return a.population() < b.population(); }  
std::sort( union, union+50, popLess ); // sort by population

PS: Оба вышеупомянутые ссылки (включая пример) являются из книги "Общепринятой истиной C++: Существенное Промежуточное Программирование" "Stephen C. Dewhurst".
Я не мог декодировать содержание темы, таким образом отправили для справки.

Заранее спасибо за Вашу справку.

10
задан Marcel Korpel 9 June 2010 в 00:58
поделиться

6 ответов

PopLess () создает временный экземпляр класса PopLess для передачи в std :: sort () . Фактически это то же самое, что если бы вы сказали (обратите внимание, что в этом примере создается дополнительная копия):

PopLess pl = PopLess();
sort(union, union + 60, pl);

Затем std :: sort () вызовет operator () на этом экземпляре.

Что касается того, что лучше "лучше" - функциональные объекты или указатели на функции, это зависит от конкретного случая. Вероятно, наиболее важным отличием является то, что объекты функций могут сохранять состояние, в то время как обычные функции, передаваемые по указателю, не могут. Компилятор может лучше оптимизировать одно или другое, но в большинстве сценариев использования это, вероятно, не важно.

8
ответ дан 3 December 2019 в 20:40
поделиться

Вопрос 1: PopLess() создает объект типа PopLess и sort, затем использует этот объект для сортировки элементов в диапазоне с помощью оператора ().

Если рассматривать функцию for_each, то она может быть проще, ее можно реализовать следующим образом:

template <typename IterT, typename Function>
Function for_each( IterT first, IterT last, Function f ) {
    for( ; first != last; ++first )
        f(*first);

    return f;
}

Итак, в основном for_each и sort, и функции, использующие объекты функций, просто берут экземпляр вашего объекта функции и вызывают его operator ().

Q2: Компилятор может оптимизировать вызов функции путем инлайнинга, если вы используете объект функции, а не указатель функции, это может быть не так просто для компилятора сделать с указателем функции. Кроме того, объект функции может иметь состояние.

3
ответ дан 3 December 2019 в 20:40
поделиться
  • Вопрос 1: PopLess () - временный объект.
  • Вопрос 2: позволяет "функция" иметь состояние ... вы можете инициализировать объект чем угодно вам нравится, прежде чем его используют как function
0
ответ дан 3 December 2019 в 20:40
поделиться

Я не уверен, что задает вопрос 1, но PopLess () - это объект. Внутри функции сортировки у этого объекта есть метод operator (), вызываемый для сравнения элементов.

2
ответ дан 3 December 2019 в 20:40
поделиться

Вопрос 1:

PopLess() должен быть разрешен во что-то вроде PopLess > tempObject.operator(), который будет то же самое, что и выполнение оператора () на временном объекте.

Это не [расширено, как вы сказали]. PopLess() на самом деле является вызовом неявного конструктора PopLess::P opLess(). Этот код создает временный объект и передает его 3-му параметру в вызове функции.

Вопрос : 2

Извлекаем ли мы какие-либо особые преимущества использования объектов функции в сравнении с указатель функции?

В данном случае нет. Здесь ваш объект PopLess не является объектом без состояния. Можно создавать функторы (объекты функций), которые имеют внутреннее состояние.

Пример:

struct ensure_min
{
    int value;
    ensure_min(int val) : value(val) {}
    int operator()(const int& i)
    {
        return std::max(value, i);
    }
}

std::vector<int>  values;
values.push_back(-1);
values.push_back(0);
values.push_back(1);
values.push_back(2);
values.push_back(3);

std::transform(values.begin(), values.end(), 
    std::ostream_iterator<int>(std::cout, "\n"), ensure_min(1));

Этот код вывезет все числа в последовательности, гарантируя, что все числа в выходных данных имеют минимальное значение 1 (вывод либо 1 - если исходное число было меньше - либо исходное число, если исходное число было больше или равно 1).

5
ответ дан 3 December 2019 в 20:40
поделиться

Основное практическое отличие - это способность функтора поддерживать состояние. Например, при сортировке данных с несколькими столбцами функтор может иметь информацию о том, по какому столбцу следует сортировать, направление сортировки и даже правила сопоставления (чувствительность к регистру и т. Д.).

0
ответ дан 3 December 2019 в 20:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: