Boost::Signals для копирования данных C++

Недавно у меня был класс, который выглядел как

class IGraphElement{
    typedef void FuncCharPtr(char*, int) ;
public:
    void Add(FuncCharPtr* f)
    {
        FuncVec.push_back(f);
    }
    void CastData(char * data, int length){
        for(size_t i = 0 ; i < FuncVec.size(); i++){
            char* dataCopy = new char[length];
            memcpy(dataCopy, data, length);
            FuncVec[i](dataCopy, length);
        }
    }
private:
    vector<FuncCharPtr*> FuncVec ;
};

Там я давал всем подписчикам указатель на копию данных. Теперь я хочу, чтобы мой класс использовал boost. Я понимаю, что с повышением я буду свободен от typedef и вектора, вместо этого у меня будет что-то вроде

class IGraphElement{

public:
  signal<void (char*, int) > SigB;

но как мне переписать CastData, чтобы я мог контролировать данные, которые будут отправляться/передаваться подписчикам?


person Rella    schedule 30.01.2011    source источник
comment
Я хочу сохранить как можно больше управления копированием данных.   -  person Rella    schedule 30.01.2011


Ответы (1)


Вы делаете одну ошибку: вы предполагаете, что функция, которую вы вызываете, освободит ресурсы (указатель char*), которые вы ей предоставляете. Вы должны сделать что-то вроде:

void CastData(char * data, int length){
    for(size_t i = 0 ; i < FuncVec.size(); i++){
        char* dataCopy = new char[length];
        memcpy(dataCopy, data, length);
        FuncVec[i](dataCopy, length);
        delete[] dataCopy;
    }
}

Теперь о boost::signals. Сигнал просто содержит список указателей на функции. Если сигнал поднят, он просто вызывает каждую функцию в этом списке с указанными параметрами. Что-то типа:

class signal { //non-templated version
public:
    void operator() (Params) 
    {
        for (FuncList::iterator i = f_.begin(); i != f_.end(); ++i) {
            (**i)(Params);
        }
    }
private:
    typedef ... Function;
    typedef std::vector<Function> FuncList;
    FuncList f_;
}

Поскольку параметры передаются напрямую, вам придется инкапсулировать структуру данных во вспомогательный класс. Вы будете управлять памятью в конструкторе копирования.

person Community    schedule 30.01.2011
comment
моя точная точка зрения не в том, чтобы освобождать ресурсы!) Один элемент графа передает всем подписчикам копию (в будущем я надеюсь передать также исходный указатель, который у него есть в настоящее время) своих текущих сгенерированных данных. И они (если дальше этот указатель не пройдут) будут подчищать. - person Rella; 30.01.2011
comment
и как инкапсулировать структуру данных во вспомогательный класс - пожалуйста, приведите пример? - person Rella; 30.01.2011
comment
@jons34yp Теперь о boost::signals. Сигнал просто содержит список указателей на функции. Мне нужно не согласиться. Signal содержит список функторов (поэтому вы можете использовать с ним boost::bind), который является гораздо более широкой сущностью. - person Marcin; 31.01.2011
comment
@Марчин. Да, я согласен, но для иллюстративных целей ясность важнее фактической точности. - person ; 31.01.2011
comment
@Kabumbus: О, хорошо. К сожалению, это не упрощает :) Но почему бы не передать константную ссылку (или указатель) на данные? Таким образом, подписчики будут делать копии только по мере необходимости. Компилятор по-прежнему будет защищать данные от любых непреднамеренных изменений данных. - person ; 31.01.2011
comment
в общем, решение моей проблемы появилось здесь class/4845529#4845529" title="как сделать typedef для функции void, которая может быть свойством любого класса"> stackoverflow.com/questions/4845504/ - person Rella; 31.01.2011