【问题标题】:Smart pointer reference counting in C++C++ 中的智能指针引用计数
【发布时间】:2013-03-14 11:16:18
【问题描述】:

我正在阅读 Safe C++,我对引用计数有疑问。下面代码的注释部分提供了问题?

#include <iostream>

using namespace std;

template <typename T>class RefCountPtr {
public: 
    explicit RefCountPtr(T* p = NULL) {
            Create(p);      
    }

    RefCountPtr(const RefCountPtr<T>& rhs) {
        Copy(rhs);      
    }

    RefCountPtr<T>& operator=(const RefCountPtr<T>& rhs) {  
        if(ptr_ != rhs.ptr_) {
            Kill();         
            Copy(rhs);  
        }
        return *this;   
    }

    RefCountPtr<T>& operator=(T* p) {
        if(ptr_ != p) { 
            Kill();     
            Create(p);  
        }   
        return *this;
    }   
    ~RefCountPtr() {
        Kill();
    }
    T* Get() const {
        return ptr_; 
    }

    T* operator->() const { 
        // SCPP_TEST_ASSERT(ptr_ != NULL, "Attempt to use operator -> on NULL pointer.");   
        return ptr_;    
    }   

    T& operator* () const { 
        // SCPP_TEST_ASSERT(ptr_ != NULL, "Attempt to use operator * on NULL pointer.");
        return *ptr_;   
    }

    int GetCount() { return *count_; }
private:    
    T*  ptr_;
    int*    count_;

    void Create(T* p) { 
        ptr_ = p;   
        if(ptr_ != NULL) {
            count_ = new int;
            *count_ = 1;    
        } else {
            count_ = NULL;  
        }   
    }   

    void Copy(const RefCountPtr<T>& rhs) {  
        ptr_ = rhs.ptr_;
        count_ = rhs.count_;
        if(count_ != NULL)  
            ++(*count_);
    }   

    void Kill() {   
        if(count_ != NULL) {
            if(--(*count_) == 0) {  
                delete ptr_;    
                delete count_;  
            }   
        }   
    }
};

void main()
{

    int* pFirstInt = new int;

    RefCountPtr<int> refPointer(pFirstInt);

    cout << "count: " << refPointer.GetCount() << std::endl;

    RefCountPtr<int> refSecondPointer = refPointer; // this calls copy constructor.

    cout << "second count: " << refSecondPointer.GetCount() << std::endl;

    RefCountPtr<int> refThirdPointer;
    refThirdPointer = pFirstInt; **// Question why are we not incrementing same int pointer? How can we correct this?
                                 // If we are not incrementing same pointer why author has provided 
                                 // operator = for data type T? 
                                 // Note: As expected program is crashing while exiting as we are deleting int pointer twice.**

    std::cout << "Third pointer: " << refThirdPointer.GetCount() << std::endl;

    RefCountPtr<int> refFourthPointer;
    refFourthPointer = refSecondPointer;

    cout << "Fourth count: " << refFourthPointer.GetCount() << std::endl;

    return;
}

/*
count: 1
second count: 2
Third pointer: 1
Fourth count: 3
Press any key to continue . . .

*/

【问题讨论】:

  • 呃。没有std::shared_ptr::operator=(T*)是有原因的。
  • 你不应该这样做:int* pFirstInt = new int; RefCountPtr&lt;int&gt; refPointer(pFirstInt)。请改用RefCountPtr&lt;int&gt; refPointer = new int
  • @meh 当我使用 RefCountPtr refPointer = new int 我收到编译错误无法从 'int *' 转换为 'RefCountPtr'
  • @venkysmarty - 因为构造函数是explicit?
  • @Zeta 那是什么原因?缺少从 shared_ptr 到原始指针(反之亦然)的隐式转换正是我不喜欢标准智能指针的原因。

标签: c++


【解决方案1】:

问题在于:

refThirdPointer = pFirstInt;

从一个已经被另一个智能指针管理的原始指针分配。

因此,您最终有两个不相关的智能指针试图管理 pFirstInt。它们是不相关的,因为它们有各自的引用计数,并且幸福地不知道彼此的存在。这会导致您观察到的双重删除。

【讨论】:

  • @ NPE 这是否意味着我应该在类定义中删除 RefCountPtr& operator=(T* p) 以避免这种情况。我不明白为什么作者提供了呢?
  • @venkysmarty:我认为这很危险。因此,我个人要么将其删除,要么将其称为其他名称(例如 reset() 以模仿 std::shared_ptr)。
猜你喜欢
  • 2015-10-30
  • 1970-01-01
  • 2016-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-20
  • 2010-10-18
  • 1970-01-01
相关资源
最近更新 更多