2012-03-30 84 views
0

我需要一個未在堆上分配的對象的引用計數器。C++:對象的引用計數器

我需要它來實現的,不能輕易複製和破壞對象RAII機制:

class File 
{ 
private: 
    int fd; 
public: 
    File(const std::string &path) ... // opening file 
    destroy();       // actually closing file 

    File(const File &f) ...   // just copying the fd 
    ~File();       // doing nothing 
} 

對於這樣一個std::shared_ptr的情景通常用於:構造函數和對象的析構函數,其指針共享被調用一次。

但是在我的情況下,我寧願避免在堆上分配對象。我需要一個類似std::shared_ptrshared_object類,以便我的類的非複製構造函數和destroy函數(在上例中)只被調用一次。

這樣的事情是否存在?

+0

@NiklasB。析構函數需要做一些引用計數。 'shared_ptr'已經擁有所有內置的邏輯。 – 2012-03-30 01:44:36

+0

@R。馬蒂尼奧:謝謝,我也意識到這一點。再看一眼代碼永遠不會受到傷害(: – 2012-03-30 01:46:31

+0

)如果你不打算在堆上維護引用計數,你打算如何維護引用計數? – 2012-03-30 01:50:43

回答

1

如果要在動態存儲(「在堆上」)分配沒有任何共享指針行爲,您可以查看various smart pointer implementation strategies。在Modern C++ Design中,作者在「智能指針」一章中討論了許多這些策略,它們是freely (and legally) available online

您將感興趣的技術是參考鏈接。使用這種技術,智能指針對象在雙向雙向鏈表中鏈接在一起,而不是指向動態分配的引用計數器。


之所以這麼說,使用std::shared_ptrstd::unique_ptr或助推變種可能會快寫,更容易維護。如果動態分配和引用計數永遠是瓶頸(我懷疑它會是什麼,但是我們不能一概而論),您可以花時間使用自定義引用鏈接版本。

0

您可以將自己的刪除器提供給std :: shared_ptr,該std :: shared_ptr將調用您的自定義銷燬函數而不是刪除。

class File 
{ 
private: 
    int fd; 
public: 
    static void destroyThis(File* f){f->destroy();} 
    File(const std::string &path) ... // opening file 
    void destroy();       // actually closing file 

    File(const File &f) ...   // You probably don't need this anymore. 
    ~File();       // doing nothing 
}; 

File fileObj("path"); 
std::shared_ptr<File> pf(&fileObj,std::bind(&File::destroyThis,std::placeholders::_1)); 
std::shared_ptr<File> pf2(pf); 
0

我相信下面的架構滿足您的要求:保持重複的文件實例之間

// pseudo-code 
class File 
{ 
private: 
    int fd; 
    File* prev; 
    File* next; 
public: 
    File(const std::string &path) : 
     fd(open(path)), 
     prev(0), 
     next(0) 
    {} 

    void destroy() 
    { 
     close(fd); 
    } 

    File(const File &f) 
     fd(f.fd), 
     prev(&f), 
     next(f.next) 
    { 
     if (next) 
      next->prev = this; 

     f.next = this; 
    } 


    ~File() 
    { 
     if (prev) 
      prev->next = next; 

     if (next) 
      next->prev = prev; 

     if ((!prev) && (!next)) 
      destroy(); 
    } 
}; 

一個雙向鏈表。列表的最後一個成員,因此最後的重複調用會被銷燬。不需要堆分配。

(顯然,這不是線程安全的,你可以用互斥鎖保護,也可以使用無鎖的方法,來維護該列表。)

+0

缺少'operator =',在拷貝構造函數中修改'const'對象中的成員等。 – 2012-03-30 05:03:05

+0

@AndréCaron:謝謝,不打算成爲成品。只是一個快速的塗鴉來傳達建築。 const_cast可以用來修改next和prev,而operator =的實現很簡單。 – 2012-03-30 06:35:43

+0

更習慣的方法是將'next'和'prev'成員聲明爲'mutable'而不是使用'const_cast <>()',但是我的觀點是你應該提到它在帖子中不完整的事實。 – 2012-03-30 14:11:56