最近用到_bstr_t。智能指针内部有计数机制,但有个问题没明白:_bstr_t A("test");     ----------->  此时对象A中计数为 1 。
_bstr_t B(A); _bstr_t 类的拷贝构造函数原型如下:
_bstr_t::_bstr_t(const _bstr_t& s) throw()
    : m_Data(s.m_Data)   -----------> 赋值。此时对象B中的计数应该和A相等,为 1 吧?
{
    _AddRef();           -----------> B中的计数加1,此时应该为 2吧?
}此时是不是应该有什么机制使A的计数也相应增加?否则释放A时,A的计数减1后为0相应内存直接就释放了,但B还引用着呢。
好纠结啊。

解决方案 »

  1.   

    被引用的对象是m_Data,这个对象内部记录引用次数,在A构造后,引用次数是1,B构造后,引用次数是2,如果A释放,引用次数变成1,A、B都释放后引用次数变成0,此时才会释放m_Data。
      

  2.   

    inline unsigned long _bstr_t::Data_t::AddRef() throw()
    {
        InterlockedIncrement(reinterpret_cast<long*>(&m_RefCount));
        return m_RefCount;
    }
    这是 _AddRef()的定义,其中m_RefCount是对象中的计数值,确实进行加一操作了啊。其次,这个拷贝构造函数在赋值时并没有创建新的空间存放值,只是将指针指向了已有的控件。即现在对象A和对象B指向的是同一块内存。
    class _bstr_t {
    public:
        // Constructors
        //
        _bstr_t() throw();
        _bstr_t(const _bstr_t& s) throw();
        _bstr_t(const char* s) ;
        _bstr_t(const wchar_t* s) ;
        _bstr_t(const _variant_t& var) ;
        _bstr_t(BSTR bstr, bool fCopy) ;    // Destructor
        //
        ~_bstr_t() throw();    // Assignment operators
        //
        _bstr_t& operator=(const _bstr_t& s) throw();
        _bstr_t& operator=(const char* s) ;
        _bstr_t& operator=(const wchar_t* s) ;
        _bstr_t& operator=(const _variant_t& var) ;    // Operators
        //
        _bstr_t& operator+=(const _bstr_t& s) ;
        _bstr_t operator+(const _bstr_t& s) const ;    // Friend operators
        //
        friend _bstr_t operator+(const char* s1, const _bstr_t& s2) ;
        friend _bstr_t operator+(const wchar_t* s1, const _bstr_t& s2) ;    // Extractors
        //
        operator const wchar_t*() const throw();
        operator wchar_t*() const throw();
        operator const char*() const ;
        operator char*() const ;    // Comparison operators
        //
        bool operator!() const throw();
        bool operator==(const _bstr_t& str) const throw();
        bool operator!=(const _bstr_t& str) const throw();
        bool operator<(const _bstr_t& str) const throw();
        bool operator>(const _bstr_t& str) const throw();
        bool operator<=(const _bstr_t& str) const throw();
        bool operator>=(const _bstr_t& str) const throw();    // Low-level helper functions
        //
        BSTR copy(bool fCopy = true) const ;
        unsigned int length() const throw();    // Binary string assign
        //
        void Assign(BSTR s) ;    // Get the physical BSTR
        //
        BSTR& GetBSTR() ;
        BSTR* GetAddress() ;    // Attach to the internal BSTR w/o copying
        //
        void Attach(BSTR s) ;    // Detach the internal BSTR
        //
        BSTR Detach() throw();private:
        // Referenced counted wrapper
        //
        class Data_t {
        public:
            // Constructors
            //
            Data_t(const char* s) ;
            Data_t(const wchar_t* s) ;
            Data_t(BSTR bstr, bool fCopy) ;
            Data_t(const _bstr_t& s1, const _bstr_t& s2) ;        // Reference counting routines
            //
            unsigned long AddRef() throw();
            unsigned long Release() throw();
            unsigned long RefCount() const throw();        // Extractors
            //
            operator const wchar_t*() const throw();
            operator const char*() const ;        // Low-level helper functions
            //
            const wchar_t* GetWString() const throw();
            wchar_t*& GetWString() throw();
            const char* GetString() const ;        BSTR Copy() const ;
            void Assign(BSTR s) ;
            void Attach(BSTR s) throw();
            unsigned int Length() const throw();
            int Compare(const Data_t& str) const throw();        // Exception agnostic wrapper for new
            //
            void* operator new(size_t sz);              private:
            BSTR         m_wstr;
            mutable char*   m_str;
            unsigned long   m_RefCount;        // Never allow default construction
            //
            Data_t() throw();        // Never allow copy
            //
            Data_t(const Data_t& s) throw();        // Prevent deletes from outside. Release() must be used.
            //
            ~Data_t() throw();        void _Free() throw();
        };private:
        // Reference counted representation
        //
        Data_t* m_Data;private:
        // Low-level utilities
        //
        void _AddRef() throw();
        void _Free() throw();
        int _Compare(const _bstr_t& str) const throw();
    };
    这是类_bstr_t类的定义。Data_t类是嵌入其中作为成员类的,其作用是存放真正的数据,并且管理引用计数,但其负责计数的变量m_RefCount定义为unsigned long ……
    如果是指针类型就好理解了。在_bstr_t对象的复制过程中m_RefCount的值也被复制,可m_RefCount在新对象中改变时,原m_RefCount会怎么样呢?要是改变的话是通过怎样的机制呢?换句话说就是 智能指针甲和已, 甲=乙,这是甲和乙的计数应该一样是2吧? 是怎么做到的呢??
    请各位高手指点!
      

  3.   

    cnzdgs: 你好。 我没注意到...m_Data是指针类型…… 
    呵呵 谢谢大家!