簡體   English   中英

unique_ptr刪除開銷

[英]unique_ptr deleter overhead

在普通的C ++設計,大多數對象可以通過一個被刪除delete的說法, free功能,或特定庫相當於free 對於此類對象, unique_ptr Deleter實現可以是通過Empty Base Class Optimization消除的無狀態對象。 但是,某些庫需要使用另一個對象(可能包含函數指針或其他某些上下文)來從該庫中刪除對象。

typedef struct lib_object lib_object;

struct lib_api {
  lib_object (*createInstance)();
  void (*freeInstance)(lib_object *o);
};

可以通過將lib_api指針存儲為自定義Deleter的數據成員來將其包裝在unique_ptr ,但是如果需要管理多個lib_object實例(例如在容器中),則會使跟蹤對象的內存開銷加倍。 在處理此庫時,可以使用哪種模式來維護RAII原則,同時仍保持內存效率?

如果只有一個lib_api對象,那么你可以讓你的刪除器獲得一個靜態指針。

如果可以有多個lib_api對象,那么除了在Deleter中存儲指向它的指針之外別無選擇。

我為這些對象使用自定義刪除器模板。

template<typename T, T Function>
struct function_deleter
{
    template<typename U>
    auto operator()(U&& u) const noexcept(noexcept(Function(std::forward<U>(u))))
    {
        return Function(std::forward<U>(u));
    }
};

然后你可以free使用你的刪除電話:

unique_ptr<int, function_deleter<void(*)(void*), &free>> uniq;

它的大小仍然等於一個指針。 現場演示

來C ++ 17您將能夠將auto用於非類型模板參數,將代碼簡化為:

template<auto Function>
struct function_deleter
{
    template<typename U>
    auto operator()(U&& u) const noexcept(noexcept(Function(std::forward<U>(u))))
    {
        return Function(std::forward<U>(u));
    }
};

unique_ptr<int, function_deleter<&call_free>> uniq;

現場演示

有了這個,在你的情況下,我將保留一個unique_ptr<pair<lib_object, lib_api>>與靜態刪除器支持這種結構。

using lib_pair = pair<lib_object, lib_api>;

void lib_free(lib_pair* p){
    p->second.freeInstance(p->first);
    delete p;
}


using unique_lib_ptr = unique_ptr<lib_pair, function_deleter<void(*)(lib_pair*), &lib_free>>

這看起來更像緩存,但可能只是你的事情。

應該存在一個更優雅的解決方案,但我會寫一些類似的東西

template <class ContainerType>
class TObjectContainer : public ContainerType {
  public:
   TObjectContainer() = default;
   TObjectContainer(const TObjectContainer&); // should call createCopy 
   TObjectContainer(TObjectContainer&&) = default;
   ~TObjectContainer()
     { for (lib_object* element : *this)
         (*freeInstance)(element);
     }

  private:
   void (*freeInstance)(lib_object *o);
};

typedef TObjectContainer<std::vector<lib_object*>> ObjectVector;

它不使用unique_ptr但它基本上應該完成這項工作。

請注意,您可能會重載每個刪除方法,例如clear ,調用freeInstancepop_back來返回原始的std::unique_ptr

暫無
暫無

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

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