簡體   English   中英

作用域std :: unique_ptr投

[英]Scoped std::unique_ptr cast

我目前正在使用智能指針來編寫一些代碼,在這些代碼中,有必要在許多點上將這些指針轉換為它們的基本類型,並將它們作為const參數傳遞給函數。 目前,我正在使用shared_ptr和標准的指針轉換函數來實現此目的,但這似乎效率低下(因為每個轉換至少要花費一個CAS)並且還會產生誤導性(因為我們沒有對共享關系進行建模,因此父級是該項的唯一所有者)物體)。

因此,我想出了以下方法,但想檢查一下它是否確實安全,或者是否有一些邊緣情況會破壞它?

template <typename ToType, typename FromType>
class FTScopedCastWrapper {
public:
    explicit FTScopedCastWrapper(std::unique_ptr<FromType>& p) : from_ptr_(&p) {
        auto d = static_cast<ToType *>(p.release());
        to_ptr_ = std::unique_ptr<ToType>(d);
    }

    ~FTScopedCastWrapper() {
        auto d = static_cast<FromType *>(to_ptr_.release());
        (*from_ptr_) = std::unique_ptr<FromType>(d);
    }

    const std::unique_ptr<ToType>& operator()() {
        return to_ptr_;
    }


    // Prevent allocation on the heap
    void* operator new(size_t) = delete;
    void* operator new(size_t, void*) = delete;
    void* operator new[](size_t) = delete;
    void* operator new[](size_t, void*) = delete;

private:
    std::unique_ptr<FromType>* from_ptr_;
    std::unique_ptr<ToType> to_ptr_;
};

template <typename ToType, typename FromType>
FTScopedCastWrapper<ToType, FromType> FTScopedCast(std::unique_ptr<FromType>& p) {
    return FTScopedCastWrapper<ToType, FromType>(p);
}

然后使用預期用途

void testMethod(const std::unique_ptr<Base>& ptr) {
    // Do Stuff
}

auto ptr = std::make_unique<Derived>();
testMethod(FTScopedCast<Base>(ptr)());

刪除器不會隨身攜帶,因為這樣做會阻止向上轉換。 這樣做也是沒有意義的,因為無論如何都不會在創建的智能指針上調用刪除程序。

防止在堆上進行分配,因為它可能允許包裝器使用它包裝的指針,並通過std :: unique_ptr成員阻止復制,並且標准銷毀順序將確保在銷毀原始指針之前將其返回到原始智能指針,即使在與包裝器相同的作用域中聲明了它。

我知道這不是線程安全的,但我認為在線程之間共享unique_ptr違反了其與單個所有者的合同。

如果我對您的理解正確,目的是在函數調用期間“竊取” std::unique_ptr的內容,然后在函數調用完成后將其返回給其原始所有者。

但這似乎不必要地令人費解。 首先,正如@TheUndeadFish在注釋中指出的那樣,您可以僅使用原始的Base*作為函數參數,並使用std::unique_ptr::get()調用。 只要被調用的函數不會對傳入的指針執行諸如調用delete類的愚蠢操作,或者將其松散在靜態變量中以備后用,那么它將正常工作。

另外,如果您發現原始指針完全令人討厭,則可以使用非所有者的指針包裝,如下所示(未經測試,但您知道了):

template <typename T>
class unowned_ptr {
public:
    unowned_ptr() = default;
    unowned_ptr(const unowned_ptr&) = default;
    unowned_ptr& operator=(const unowned_ptr&) = default;

    template <typename U>
    unowned_ptr(const U* other) : ptr(other) {}

    template <typename U>
    unowned_ptr(const std::unique_ptr<U>& other) : ptr(other.get()) {}

    T* operator->() { return ptr; }
    const T* operator->() const { return ptr; }

private:
    T* ptr = nullptr;
};

與此非常相似的是,有人為C ++ 17提出了std::observer_ptr (“世界上最愚蠢的智能指針”),但是我不確定它的狀態。

暫無
暫無

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

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