#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
.