2010-10-15 24 views
0

這是我的問題。 我有一個課程來創建定時事件。它發生在:爲延遲事件參數分配內存

void (*func)(void* arg)

的函數指針void*的說法

延遲

的問題我可能要在其中創建即時,我不想變量成爲類中的靜態變量或全局變量。如果這些不符合,我不能做這樣的事情:

void doStuff(void *arg) 
{ 
    somebool = *(bool*)arg; 
} 

void makeIt() 
{ 
bool a = true; 
    container->createTimedEvent(doStuff,(void*)&a,5); 
} 

這不會工作,因爲布爾函數返回時被破壞。所以我必須在堆上分配這些。問題就變成了誰分配和誰刪除。我想要做的是能夠接受任何事情,然後複製其內存並在定時事件類中進行管理。但我不認爲我可以做memcpy,因爲我不知道tyoe。

在時間事件負責內存管理的情況下,實現此目標的好方法是什麼?

感謝

我不使用升壓

class AguiTimedEvent { 
    void (*onEvent)(void* arg); 
    void* argument; 
    AguiWidgetBase* caller; 
    double timeStamp; 
public: 
    void call() const; 

    bool expired() const; 
    AguiWidgetBase* getCaller() const; 
    AguiTimedEvent(); 
    AguiTimedEvent(void(*Timefunc)(void* arg),void* arg, double timeSec, AguiWidgetBase* caller); 
}; 

void AguiWidgetContainer::handleTimedEvents() 
{ 
    for(std::vector<AguiTimedEvent>::iterator it = timedEvents.begin(); it != timedEvents.end();) 
    { 
     if(it->expired()) 
     { 

      it->call(); 
      it = timedEvents.erase(it); 
     } 
     else 
      it++; 
    } 
} 

void AguiWidgetBase::createTimedEvent(void (*func)(void* data),void* data,double timeInSec) 
{ 
    if(!getWidgetContainer()) 
     return; 
    getWidgetContainer()->addTimedEvent(AguiTimedEvent(func,data,timeInSec,this)); 
} 


void AguiWidgetContainer::addTimedEvent(const AguiTimedEvent &timedEvent) 
{ 
    timedEvents.push_back(timedEvent); 
} 
+0

爲了澄清,你想'somebool'堅持?以後什麼時候使用它?爲什麼你不能使用'a'? 「doStuff」應該是你的時間事件類的成員嗎? – JoshD 2010-10-15 18:07:32

+0

@JoshD稍後當計時器說它已過期時使用它,這意味着在此之前將會關閉堆棧 – jmasterx 2010-10-15 18:08:41

+0

它們是在計時器上調用的事件 – jmasterx 2010-10-15 18:09:01

回答

1

爲什麼你會不使用boost::shared_ptr

它提供了您需要的存儲持續時間,因爲只有當所有指向它的shared_ptrs都被破壞時纔會破壞底層對象。

此外它提供完整的線程安全。

+0

非升壓解決方案呢? – jmasterx 2010-10-15 18:12:51

+2

@Milo:'shared_ptr'是TR1和C++ 0x的一部分。如果沒有別的,如果你不想使用第三方庫,沒有什麼能夠阻止你編寫自己的智能指針。 – 2010-10-15 18:14:36

+0

寫點東西。使用引用計數的任意指針類型的簡單包裝。解決方案會比boost更清晰,因爲根本不瞭解線程安全性。 – Keynslug 2010-10-15 18:20:21

1

使用C++ 0x unique_ptr非常適合這項工作。這是未來的標準,但在G ++和Visual Studio中已經支持unique_ptr。對於C++ 98(當前標準),auto_ptr的工作方式與使用unique_ptr版本相比非常困難...對於C++ TR1(在Visual Studio和G ++中實現),您可以使用std :: tr1 :: shared_ptr。

基本上,你需要一個智能指針。下面是的unique_ptr將如何工作:

unique_ptr<bool> makeIt(){ // More commonly, called a "source" 
    bool a = true; 
    container->createTimedEvent(doStuff,(void*)&a,5); 
    return new unique_ptr<bool>(a) 
} 

當您使用代碼後...

void someFunction(){ 
    unique_ptr<bool> stuff = makeIt(); 
} // stuff is deleted here, because unique_ptr deletes 
    // things when they leave their scope 

您也可以使用它作爲一個功能 「下沉」

void sink(unique_ptr<bool> ptr){ 
    // Use the pointer somehow 
    } 

    void somewhereElse(){ 
     unique_ptr<bool> stuff = makeIt(); 
     sink(stuff); 
     // stuff is now deleted! Stuff points to null now 
    } 

除了,除了奇怪的移動規則之外,你可以像普通指針一樣使用unique_ptr。有很多智能指針,unique_ptr只是其中之一。 shared_ptr是在Visual Studio和G ++中實現的,並且是更典型的ptr。我個人喜歡儘可能經常使用unique_ptr。

+0

這將如何與tr1 :: sharedptr協同工作? – jmasterx 2010-10-15 18:18:09

+0

std :: tr1 :: shared_ptr正好* boost :: shared_ptr(以及... boost :: shared_ptr的舊版本)。 shared_ptr基本上像Python的垃圾收集一樣工作。詳情請參閱他答案中的鏈接。 – Dragontamer5788 2010-10-15 18:31:21

+0

我應該添加:shared_ptr比unique_ptr更易於使用。但是每個人都在談論shared_ptr ......所以上面是一個稍微不同的方法。 – Dragontamer5788 2010-10-15 19:06:25

0

如果你不能使用boost或tr1,那麼我要做的就是編寫自己的函數,其行爲與auto_ptr相似。事實上,這就是我在這裏完成的項目,沒有任何提升或tr1訪問。當所有關心數據的事件都完成後,它會自動被刪除。

+0

auto_ptr是標準的C++ 98 – Dragontamer5788 2010-10-15 18:50:28

0

只需更改函數定義即可獲取表示傳入對象大小的額外參數,然後只需將大小向下傳遞即可。所以,你的新函數聲明如下:

void (*func)(void* arg, size_t size) 

void doStuff(void *arg, size_t size) 
{ 
    somebool = *(bool*)arg; 
    memcpy(arg, myStorage, size); 
} 


void makeIt() 
{ 
    bool a = true; 
    container->createTimedEvent(doStuff,(void*)&a,sizeof(bool), 5); 
} 

那麼你可以傳遞的是仍然在棧中的變量,並在定時事件類memcpy的他們。唯一的問題是,你不知道這種類型...但是這是當你投擲無效*

希望有所幫助。

0

您應該重新使用您的類來使用繼承,而不是函數指針。

class AguiEvent { 
    virtual void Call() = 0; 
    virtual ~AguiEvent() {} 
}; 

class AguiTimedEvent { 
    std::auto_ptr<AguiEvent> event; 
    double timeSec; 
    AguiWidgetBase* caller; 
public: 
    AguiTimedEvent(std::auto_ptr<AguiEvent> ev, double time, AguiWidgetBase* base) 
     : event(ev) 
     , timeSec(time) 
     , caller(base) {} 
    void call() { event->Call(); } 

    // All the rest of it 
}; 

void MakeIt() { 
    class someclass : AguiEvent { 
     bool MahBool; 
    public: 
     someclass() { MahBool = false; } 
     void Call() { 
      // access to MahBool through this. 
     } 
    }; 
    something->somefunc(AguiTimedEvent(new someclass())); // problem solved 
}