簡體   English   中英

所有權以及如何避免shared_ptr

[英]Ownership and how to avoid shared_ptr

我正在嘗試為游戲引擎編寫一個簡單的事件管理器類和監聽器。 在通常的實現(即McShaffry )中,事件管理器注冊偵聽器,這些偵聽器原則上將 shared_ptr作為私有成員保存到偵聽器。

我在許多情況下看到人們說應該避免使用shared_ptr和喜歡的東西(例如這里 )。 因此,我試圖找到實現事件管理器的方法,而不共享監聽器的所有權。

我想到的一種方法是為偵聽器分配唯一的id並使用事件管理器注冊它們的id。 然后聽眾負責在事件管理員更新后“詢問”事件管理員,如果他們的id下有任何事件可用。

我想問一下,在這種情況下是否有更清潔和/或標准的方法來避免共享所有權,但一般情況下也是如此。 例如,我對偵聽器有同樣的問題。 偵聽器需要存儲指向其父級(或它們正在偵聽的對象)的指針,以便在處理事件時可以調用其方法。

作為墊的評論說,沒有理由不使用一般智能指針。 也就是說,警示警告似乎確實適用於您的情況:據我所知,您沒有共享所有權; 事件管理員擁有聽眾的唯一所有權。 因此, shared_ptr在這里是不合適的。

另一種方法是使用unique_ptr ,它在很多方面都是shared_ptr硬幣的另一面。 但是,通過簡單地將具體實例保存到事件管理器,即使可以避免對聽眾建模的方式。 如果沒有更詳細的描述,就不可能說你是否需要指針,但如果你不需要它們,那么,建議適用:當具體對象可以使用時,不要使用(智能)指針。

最后,如果您的偵聽器是其所有權在其他地方管理的對象,則考慮簡單地使用指向這些對象的原始指針:在這種情況下,事件管理器根本不是對象的所有者 - 既不是唯一所有者也不是共享所有者。 雖然這對我來說是首選方式,但它需要仔細分析監聽器的生命周期,以確保事件管理器不會指向不再存在的監聽器。

shared_ptr往往被濫用; 例如,通常建議將SO作為模糊指針問題的解決方案。 它不能替代好的設計,除非有一個基於理解正在編寫的代碼中的對象生存期問題的設計,否則不應該使用它。

從個人經驗來看, shared_ptr很棒,但有時可能不是正確的工具。 如果代碼完全在您的控制之下,99.9%的時間, shared_ptr可能會讓您的生活更輕松。 你確實需要確保你不這么認為:

Foo *f = new Foo();
shared_ptr<Foo> fptr(f);
shared_ptr<Foo> fptr2(f);

這將導致f的內存被fptr1fptr2 相反,你想做的事情如下:

Foo *f = new Foo();
shared_ptr<Foo> fptr(f);
shared_ptr<Foo> fptr2 = fptr;

在第二種情況下,將一個共享指針分配給另一個共享指針將增加引用計數。

另一個你可以使用shared_ptr遇到問題的地方是你需要將一個裸指針傳遞給一個函數(如果你需要將作為方法的第一個參數傳遞給你,或者你依賴的是第三方庫) 。 您可以從shared_ptr獲取裸指針,但不能保證它指向的內存地址仍然存在,因為引用計數器不會遞增。

您可以通過保留額外的shared_ptr來解決這個問題,盡管這可能很麻煩。

還有其他形式的智能指針。 例如,OpenSceneGraph有一個ref_ptr ,它比shared_ptr更容易使用。 一個警告是,它指向的所有對象必須從Referenced下降。 但是,如果你對此感到滿意,我認為真正發生非常糟糕的事情要困難得多。

在某些情況下, shared_ptr是過度殺戮或者沒有正確地解釋所需的語義(例如傳遞所有權)。

您需要做的是查看您的設計並查看您需要的所有權模型。 如果您需要/想要共享所有權,那么只需使用shared_ptr進行建模。 如果共享/參考計數的所有權不合適,請使用另一個智能指針。

難道你的情況不適合這里描述的auto_ptr的好用: http//www.gotw.ca/publications/using_auto_ptr_effectively.htm (本周的大師«有效地使用auto_ptr)

根據我的理解,您構建一個監聽器,然后將其提供給事件管理器。 因此,事件管理器可以被視為“接收器”。

使用auto_ptr技術,您的事件管理器可以干凈利落地安全地獲取您給予他的監聽器的完全所有權。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM