Хобрук: Ваш путь к мастерству в программировании

Дополнительные конструкторы копирования при использовании std::function

В моем проекте есть два компонента: производитель и потребитель. Производитель несет ответственность за обработку некоторой информации и предоставление результата потребителю. Результат передается с помощью объекта функции.

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

#include <iostream>
#include <vector>
#include <functional>

using namespace std;

class Data {
    std::vector<int> vec;
public:
    Data()  { 
        cout << "Data()" << endl; 
    }

    Data(const Data& rr) : vec(rr.vec)  {
        cout << "Data(Data&)" << endl;
    }

    ~Data() {
        cout << "~Data()" << endl;
    }

    Data(Data&& rr) : vec(move(rr.vec)) {
        cout << "Data(Data&&)" << endl;
    }

    void get() {
    }
};

class Producer {
public:
    void process(function<void(Data)> f) {
        Data data; 
        f(move(data));
    }

    void process2(void(&pf)(Data))  {
        Data c; 
        pf(move(c));
    }

};

void Consume(Data a) {
    cout << "Consume(data)" << endl;
}

int main() {
    {
        cout << "use function() " << endl;
        Producer p;
        p.process([](Data a) {
            cout << "Consume(data)" << endl;
        });
    }

    {
        cout << endl;
        cout << "use function pointer" << endl;
        Producer p;;
        p.process2(Consume);
    }
    return 0;
}

он имеет следующий вывод

    use function() 
    Data()
    Data(Data&&)
    Data(Data&)
    Data(Data&)
    Consume(data)
    ~Data()
    ~Data()
    ~Data()
    ~Data()

    use function pointer
    Data()
    Data(Data&&)
    Consume(data)
    ~Data()
    ~Data()

Существуют дополнительные конструкторы копирования, когда используется объект функции.

Я сделал что-то не так? Можно ли избавиться от этих лишних конструкторов?

Заранее спасибо.

Я использую VC10 SP1.


  • С g++ он просто вызывает конструктор перемещения 3 раза. 20.12.2011
  • std::function большой и дорогой... надеюсь, у вас хорошая оптимизация компилятора, но есть предел тому, сколько можно оптимизировать, учитывая огромную гибкость, которую предлагает вам std::function. В критических случаях предпочтите указатели функций или auto/лямбда явному преобразованию в std::function, когда важна производительность. 20.12.2011
  • Это будет исправлено в MSVC11. См. мой ответ здесь: title="как сделать хранение лямбда-объектов c более эффективным">stackoverflow.com/questions/8203211/ 20.12.2011
  • ваш производственный код использует тот же самый поток выполнения? 20.12.2011
  • @refp, похоже, но нет. Я пытался заменить const T& на T в аргументах функции, но это не так эффективно, как я ожидал. 21.12.2011
  • @Сеник; Вместо этого передайте ссылку, нет необходимости в конструкторах копирования и тому подобном. Шаблон может быть разработан для работы с этим подходом, а не с тем, который вы используете в настоящее время. 21.12.2011

Ответы:


1

Здесь у вас есть несколько вариантов.

  • Не используйте std::function, ваша незахватывающая лямбда конвертируется в void(*)(Data)
  • Не используйте std::function, сделайте свои шаблоны функций, компилятор может вывести скрытый тип лямбды.
  • Не копируйте объекты, передавайте их как указатели или ссылки. В зависимости от того, что делает полная версия программы, может оказаться более эффективным выделить память в куче и использовать std::unique_ptr.
18.01.2012
Новые материалы

Решения DBA Metrix
DBA Metrix Solutions предоставляет удаленного администратора базы данных (DBA), который несет ответственность за внедрение, обслуживание, настройку, восстановление базы данных, а также другие..

Начало работы с Блум
Обзор и Codelab для генерации текста с помощью Bloom Оглавление Что такое Блум? Некоторые предостережения Настройка среды Скачивание предварительно обученного токенизатора и модели..

Создание кнопочного меню с использованием HTML, CSS и JavaScript
Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

Внедрите OAuth в свои веб-приложения для повышения безопасности
OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

Классы в JavaScript
class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

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

Как построить любой стол
Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...