std :: map和_CrtIsValidHeapPointer错误

时间:2010-08-25 08:22:45

标签: c++ stdmap

我尝试使用std :: map with

class DEMO {
    public:
        DEMO();
        virtual ~DEMO();
        DEMO &operator =(const DEMO &d);
        DEMO(const DEMO& d);
        BYTE* Arr() const;
    private:
        BYTE *m_array;
};

DEMO &DEMO::operator =(const DEMO &d) {
    memcpy(m_array, d.Arr(), 1);
    return *this;
}

DEMO::DEMO(const DEMO& d) {
    //call operator=
    *this = d;
}

const BYTE* DEMO::Arr() const {
    return m_array;
}

DEMO::DEMO() {
    m_array = new BYTE[1];
    }

DEMO::~DEMO() {
    if (m_array != 0)
        delete [] m_array;
}

class MyClass {
    private:
        typedef map<unsigned int,DEMO> t_mapType;
        t_mapType m_map;
        void Test();
}

void MyClass::Test() {
    DEMO myDEMO;
    m_map[1] = myDEMO;
}

如果我在类中调用Test(),我会收到错误断言_CrtIsValidHeapPointer ...
我检查了断点,我看到,在assingment期间(m_map [1] = myDEMO;)DEMO的析构函数被调用,我在delete [] m_array上得到错误; - 我怎么运行?

4 个答案:

答案 0 :(得分:4)

复制构造函数和赋值运算符是错误的。在执行m_array之前,您需要为memcpy分配内存。当您尝试使用DEMOm_map[1] = myDEMO;对象插入地图时,正在创建myDEMO的副本。要创建副本,请使用DEMO类的副本。由于在执行此副本时未分配m_array的内存,因此memcpy调用正在崩溃。

答案 1 :(得分:1)

将复制ctor实现基于赋值运算符几乎总是错误的。赋值运算符必须拆除对象的旧状态并构建新状态。复制者只需要建立一个新的州 如果你想这样做,你的副本首先需要建立一个默认状态,让赋值运算符拆除。当然,这是在浪费资源。

那就是说,实际上你应该使用 复制和交换习语 来将你的作业操作符作为你的dtor并复制ctor。有关上述内容的更全面说明,请参阅here

答案 2 :(得分:0)

使用std :: vector管理您的BYTE *。

class DEMO {
    public:
        DEMO();
        virtual ~DEMO();
        //DEMO &operator =(const DEMO &d);
        //DEMO(const DEMO& d);
        const std::vector<BYTE>& Arr() const;
    private:
        std::vector<BYTE> m_array;
};

// Doesn't even need to be implemented by us anymore
//DEMO &DEMO::operator =(const DEMO &d) {
//    memcpy(m_array, d.Arr(), 1);
//    return *this;
//}

// Again, doesn't need to be implemented
//DEMO::DEMO(const DEMO& d) {
//    //call operator=
//    *this = d;
//}

// Just changed to return const vector&.
const std::vector<BYTE>& DEMO::Arr() const {
    return m_array;
}

// Changed to use initializer list
DEMO::DEMO() 
    : m_array(1) {
    // Old code: m_array = new BYTE[1];
}

// Doesn't need any code by us
DEMO::~DEMO() {
    //if (m_array != 0)
    //    delete [] m_array;
}

答案 3 :(得分:0)

我将我的代码更改为使用指向对象的指针而不是对象作为地图中的值部分:

typedef map<unsigned int,DEMO*> t_mapType;

所以我可以说如下:

m_map[1] = new DEMO();

我必须使用自己的free-mem方法:

void DEMO::Clear() {
    if (m_map.size() > 0) {
        for (t_mapType::const_iterator it = m_map.begin(); it != m_mp.end(); ++it) {
            if (it->second != 0)
                delete it->second;
        }
        m_map.clear();
    }
}