std::bind находится в стеке?

#c #stdbind

#c #стандартная привязка #c #stdbind

Вопрос:

Я хочу передать функцию обратного вызова члена c objcet в библиотеку «c», которая просто имеет void *. Затем я использую std::function для регистрации обработчика обратного вызова. Но возникает проблема, когда я преобразую std::function<>* в void*, кажется, что std::function<> * уничтожается при приведении к void *.

Ниже приведен тестовый код.

 #include <iostream>
#include <functional>

class TfLight {
 public:
  void print(int a) {
    std::cout << "TfLight::print " << a << std::endl;
  }
};

class Server {
 public:
  void run(int a) {
    std::function<void(int)>* func = reinterpret_cast<std::function<void(int)>*>(ptr);
    std::cout << func << std::endl;
    (*func)(a);
  }
  
  void register(std::function<void(int)> tf) {
    std::cout << (amp;tf) << std::endl;
    // f = tf;
    setPtr(amp;tf);
  }
  
  void setPtr(void* p) {
    ptr = p;
  }
  
  std::function<void(int)> f;
  void* ptr;
};

int main()
{
    TfLight* tf = new TfLight();
    Server* server = new Server();
    server->register(std::bind(amp;TfLight::print, tf, std::placeholders::_1));
    server->run(3333);
    
    delete server;
    delete tf;
}
  

Когда я использую глобальную переменную для хранения «std::function<void(int)>», ее можно вызвать обычным способом. Как я могу справиться с этой проблемой?

Но возникает проблема, когда я преобразую std::function<>* в void*, кажется, что std::function<> * уничтожается при приведении к void*

Комментарии:

1. В стороне: вам не нужно new создавать TfLight или Server

Ответ №1:

std::bind является функцией. Это не в стеке или куче.

Его возвращаемое значение является временным объектом и имеет обычное время жизни временных объектов. Здесь проблема не в этом; bind возвращаемое значение хранится в std::function переданном в register .

В register снова соблюдаются обычные правила C . std::function<void(int)> tf) является аргументом функции, поэтому amp;tf остается действительным в течение всего времени вызова. Как только register возвращается, tf перестает существовать. Закомментированный код правильный; вы должны были скопировать его в Server::f .

Поскольку у вас есть Server::f , void* Server::ptr это кажется совершенно бессмысленным. Да, вы можете установить ptr на amp;f , но почему?

Комментарии:

1. спасибо за ваш ответ! Как я уже говорил ранее, мне нужно использовать библиотеку c. Я исправил это, изменив класс сервера c на класс c . А также мне нужно передать обработчик функции обратного вызова библиотеки c, у которой просто есть void *, поэтому я хочу попробовать это.

2. Тогда std::function похож на другой временный объект, мне нужно его сохранить. Есть ли более элегантный способ добиться этого?

3. @dahohu527: Вполне вероятно, что самое простое решение — передать весь файл Server* как void* вашему обратному вызову C. После обратного приведения внутри обратного вызова у вас есть доступ ко всем Server элементам, включая любые сохраненные std::function .