簡體   English   中英

來自同一原始指針的兩個std :: shared_ptr

[英]two std::shared_ptr from the same raw pointer

我不明白為什么要explicit shared_ptr( pointer p ); 不能保護開發人員不要將p分配給另一個shared_ptr

我的想法在這里:

#include <iostream>
#include <memory>

template <typename T>
class ptr
{
    public:
        // ctor a) for lvalues
        explicit ptr(T*& value)  : value_(value) { value=nullptr;  }

        // ctor b) for rvalues pointer reference
        explicit ptr(T*&& value) : value_(value) { }

        ~ptr() { delete value_; }

        // for simplicity this is left public
        T* value_;
};


int main(int argc, char *rgv[])
{
      {
        printf("%10s | %10s | %10s\n", "raw", "p0", "p1");
        // create a raw pointer
        // BAD practice but still could happen 
        int* raw = new int(1);
        printf("%10x | %10x | %10x\n", raw, 0, 0);

        // init p0 from raw pointer ctor (a)
        ptr<int> p0(raw);
        printf("%10x | %10x | %10x\n", raw, p0.value_, 0);

        // init p1 from the same raw poiter again ctor (a)
        ptr<int> p1(raw);
        printf("%10x | %10x | %10x\n", raw, p0.value_, 0);

        // nothing bad happens val was set to nullptr 
        // before p1 construction
      }

    // in order to construct ptr from rvalues 
    // we use ctor (b)
    ptr<int> p2(new int());

      {
        printf("\n");
        // create a raw pointer
        int* raw = new int(1);
        printf("%10x | %10x | %10x\n", raw, 0, 0);

        // init p0 from raw pointer
        std::unique_ptr<int> p0(raw);
        printf("%10x | %10x | %10x\n", raw, p0.get(), 0);

        // init "accidentally" p1 from the same raw poiter again 
        std::unique_ptr<int> p1(raw);
        printf("%10x | %10x | %10x\n", raw, p0.get(), 0);

        // CRASH: double free or corruption
      }

    return 0;
}

鑒於以上代碼,我有兩個問題:

1)我是否錯過了以這種方式實施ptr的任何要點:簡而言之,我對ptr(T*& value)ptr(T*&& value)建設者有什么看法嗎?

2)STL決定不避免這種可能的錯誤而導致原始指針在shared_ptr構造上保持不變的背后的原理是什么?

我是否錯過了以這種方式實施ptr的任何要點?

例如,如果必須將類型轉換應用於指針

struct Base {/*...*/};
struct Derived : Base {/*...*/};

Derived * d = new Derived;
ptr<Base> p(d);

那么臨時Base指針將傳遞給rvalue構造函數,而d將被保留。

(您可以使用模板構造函數來解決這個問題,但是可能還有其他子屬性)。

當然,如果用戶愚蠢到可以保留一個原始指針,那么他可能愚蠢到可以保留兩個原始指針。 該方案只會使其中之一無效。

STL決定不避免這種可能的錯誤,從而使原始指針在shared_ptr構造上保持不變的背后的原理是什么?

大概是最少驚奇的原則。

通過區分智能指針和原始指針,並始終將原始指針視為危險的野獸,可以避免此類錯誤。 這樣的局部安全網只會使發現咬傷的細微邊緣情況變得更加困難。 智能指針的慣用用法避免了原始指針,除非在異常情況下(需要特別注意),否則完全消除了與所有權相關的錯誤的可能性。

在C ++ 14中, std::make_unique (除了我們已經擁有的std::make_shared )將意味着根本不需要在代碼中出現任何new ,從而很容易避免此錯誤。

暫無
暫無

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

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