2016-01-27 249 views
-1

在下面的代碼實現執行罰款的智能指針,但最後我得到以下信息:Visual C++調試斷言失敗?

enter image description here

下面是代碼:

smart_ptr.h

#ifndef SMART_PTR_H 
#define SMART_PTR_H 

/* 
    Class: Auto_ptr 

    It implements a generic 
    smart pointer that doesn't need 
    to be deleted explicitly, i.e. 
    it provides garbage collection. 
*/ 
template<class T> 
class Auto_ptr{ 
public: 
    // constructors 
    explicit Auto_ptr(T* p = nullptr): value(p) { }; // constructor 
    Auto_ptr(Auto_ptr& p);      // copy constructor 
    Auto_ptr& operator= (const Auto_ptr& p);   // copy assignment 
    ~Auto_ptr() { std::cout << "pointer deleted\n"; delete value; }      // destructor 

    // access operators 
    const T& operator*() const { return *value; }  // dereference operator 
    const T* operator->() const { return value; }  // indirect class member access (arrow) operator 

    // non-modifying members 
    T* get() { return value; }       // getter method 
    void reset(T* v);         // reassing new value(default value: nullptr) 
    T* release();          // transfers the object to another pointer; without destroying it 
private: 
    // data member 
    T* value; 

}; 

//-------------------------------------------------------------------------------------------------------- 
// class Auto_ptr member implementations 
// Constructors 
// copy constructor 
template<class T> 
Auto_ptr<T>::Auto_ptr(Auto_ptr& p) { 
    value = p.release(); 
} 

// copy assignment 
template<class T> 
Auto_ptr<T>& Auto_ptr<T>::operator= (const Auto_ptr& p) { 
    if (this == &p) return *this; 
    if (value) delete value; 
    value = p.value; 
    return *this; 
} 

/* 
    Function: release() 
    Use: T ptr = auto_ptr_obj.release(); 

    It transfers the pointer value to the 
    caller, setting the data member value 
    to nullptr. 
*/ 
template <class T> 
T* Auto_ptr<T>::release() { 
    T* temp = value; 
    value = nullptr; 
    return temp; 
} 

/* 
    Function: reset() 
    Use: auto_ptr_obj.release(new_pointer); 

    It deletes the object pointer to by 
    pointer value and assings new_pointer; 
*/ 
template <class T> 
void Auto_ptr<T>::reset(T* v) { 
    delete value; 
    value = v; 
} 

#endif 

main.cpp

#include <iostream> 
#include "smart_ptr.h" 
#include "assert.h" 

//===================================================================== 
void test1() { 
    std::cout <<"\nTest constructor and get() member.\n"; 
    Auto_ptr<int> p(new int); 
    *p.get() = 5; 
    std::cout <<"p points to: "<< *p << "\n"; 

    //assert(*p, 5); 
    std::cout <<"TEST 1 DONE\n"; 
} 

void test2() { 
    std::cout <<"\nTest reset() and release() members.\n"; 
    Auto_ptr<int> p(new int); 
    *p.get() = 5; 
    std::cout <<"p points to: "<< *p << "\n"; 

    p.reset(new int(10)); 
    std::cout <<"reset() p points to: "<< *p << "\n"; 
    //assert(*p, 10); 

    int *temp = p.release(); 
    std::cout <<"caller of release(), temp points to: "<< *temp << "\n"; 
    //assert(*temp, 10); 

    // nullptr dereferece error 
    // std::cout <<"p after being release()d points to: "<< *p << "\n"; 

    std::cout <<"TEST 2 DONE\n"; 
} 

void test3() { 
    std::cout <<"\nTest copy constructor and copy assignment.\n"; 
    Auto_ptr<int> p1(new int(10)); 
    Auto_ptr<int> p2(p1); 

    std::cout <<"copy constructed p2 points to: "<< *p2 << "\n"; 
    //assert(*p2, 10); 

    Auto_ptr<int> p3(new int(20)); 
    p1 = p3; 
    std::cout <<"copy assigned p1 points to: "<< *p1 << "\n"; 
    //assert(*p1, 20); 

    std::cout <<"TEST 3 DONE\n"; 
} 

//===================================================================== 
int main() { 
    test1(); 
    test2(); 
    test3(); 

    getchar(); 
} 

有趣的是,在Live example錯誤不可重現。

這條消息的原因是什麼?


+0

難道你不能只用調試器來發現錯誤嗎? – juanchopanza

+1

這通常是「雙重刪除」的結果 - 在這種情況下,我懷疑它是您的副本分配。您賦值'value = p.value;'並且這兩個副本保持相同的'值'並且都嘗試刪除它。 – Niall

+2

@simplicisveritatis。複製作業,對不起 - 你也應該使用'release'。並刪除'const'。您基本上需要將指針從一個指針移到另一個指針上。 – Niall

回答

2

這通常是「雙刪除」的結果 - 在這種情況下,我懷疑這是您的副本分配。

您指定value = p.value;並且兩個副本保持相同的值,並且都嘗試刪除它。

您實質上需要將指針從一個對象移到另一個對象,就像複製構造函數一樣。您還需要刪除const