簡體   English   中英

C ++ API中的智能指針?

[英]Smart pointers in C++ APIs?

經常建議不要在現代C ++中使用原始指針,除非有少數情況。 在C ++庫API中使用智能指針的常見做法是什么?

我想到以下用例:

  1. 返回新對象的函數。
  2. 該函數返回一個新對象,但它也創建了對該對象的另一個引用。
  3. 僅使用其接收的對象作為參數的函數。
  4. 接管對象所有權的功能。
  5. 該函數將存儲對已作為參數接收到的對象的引用,但是可能存在對同一對象的其他引用(從調用者那一側)。

不幸的是,庫API的設計遠遠超出了語言本身的規則:突然,您必須關心諸如ABI之類的實現細節。

與普通實現可以輕松交互的C相反,C ++實現具有完全不同的ABI(用於VC ++的Microsoft ABI與gcc和Clang使用的Itanium ABI完全不兼容),並且C ++標准庫實現也彼此不兼容,因此如果使用std::類出現在接口中,則使用libstdc ++(與gcc捆綁在一起)編譯的庫不能被使用libstdc ++的另一個主要版本或libc ++(與Clang捆綁在一起)之類的其他實現的程序使用。

因此,這實際上取決於您是否打算將庫作為二進制文件交付,還是取決於用戶是否可以使用自己的編譯器和標准庫實現選擇來編譯庫。 僅在后一種情況下,才應公開C ++接口,因為堅持使用C的二進制發行版更好(並且更易於與其他語言集成)。


順便說一句,讓我們假設您決定使用C ++ API:

1)一個返回新對象的函數。

如果可以按值返回對象,則返回;否則,返回0。 如果它是多態的,請使用std::unique_ptr<Object>

2)一個返回新對象的函數,但它也創建了對該對象的另一個引用。

罕見的情況 我想您的意思是某種程度上已經保留了參考。 在這種情況下,您擁有共享所有權,因此顯而易見的選擇是std::shared_ptr<Object>

3)僅使用接收到的對象作為參數的函數。

甚至假設不保留對對象的引用,也比最初看起來要復雜得多。

  • 通常,通過引用傳遞(是否為const
  • 除非您打算對對象的副本進行操作,否則將通過值傳遞以受益於潛在的移動

4)接管對象所有權的功能。

簡單所有權: std::unique_ptr<Object>

5)一個函數,它將存儲對已作為參數接收到的對象的引用,但是可能存在對同一對象的其他引用(從調用方)。

共享所有權: std::shared_ptr<Object>

  1. 在一般情況下,唯一指針可以勝任。

     std::unique_ptr<Foo> func(); 

    這樣您就可以將它們直接分配給調用者站點上的auto變量,而不必擔心內存管理。

     auto u = func(); 

    如果需要共享所有權,可以在調用者站點上轉換智能指針:

     std::shared_ptr<Foo> s{func()}; 

    但是,如果函數的返回類型不是多態的, 並且該類型可以快速移動,則您可能更喜歡按值返回

     Foo func(); 
  2. 共享的指針。

     std::shared_ptr<Foo> func(); 
  3. 只需使用對對象的引用或const引用,即可在調用者站點使用原始指針或智能指針“取消引用”。

     void func(Foo& obj); void func(const Foo& obj); 

    如果參數是可選的,則可以使用原始指針,以便可以輕松地將nullptr傳遞給它們。

     void func(Foo *obj); void func(const Foo *obj); 
  4. 唯一指針。

     void func(std::unique_ptr<Foo> obj); 
  5. 常量引用共享指針。

     void func(const std::shared_ptr<Foo>& obj); 

    const引用(共享指針)只是一種優化,可以防止在調用函數和返回函數時調整引用計數。

這是一個非常古老的問題,但也是一個重要的問題。

答案中缺少一個思路,那就是如果可以幫助您,則不應從API返回原始指針智能指針。

討論了原始指針問題。 但是,智能指針也可能會被濫用,尤其是在具有復雜內部API的大型項目中。

一種解決方法是創建一個RAII / wrapper對象,該對象保存(從未公開的)智能指針。

暫無
暫無

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

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