2016-01-27 212 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