memset导致“矢量迭代器不兼容”错误

时间:2013-02-25 13:22:39

标签: c++ vector iterator memset

目前在我的DirectX游戏上工作并在常量缓冲区构造函数中使用memset(0)(或VS中的ZeroMemory宏)来初始化所有带零的值,它可以正常工作。当我意外地尝试以这种方式初始化包含向量的其他结构时出现问题。根据编译器(VS2010 / VS2012),这会导致“矢量迭代器不兼容”,std :: vector :: end更加精确。我可以理解memset可能会使向量迭代器无效,但是在我将元素推回到向量之后,为什么“结束”迭代器无法正常工作。它不应该重新定位向量将迭代器结束到正确的位置(在最后一个元素之后)?所有类型的std :: some_container :: end迭代器都受此影响吗?

#include <vector>

class MyClass
{
public:
    MyClass() { 
        memset(this, 0, sizeof(*this));
    }
    ~MyClass() {}
    std::vector<int>& GetData() { return m_data; }
    float            m_range;
private:
    std::vector<int> m_data;

};

int main()
{
    MyClass myClass;
    myClass.GetData().push_back(1);
    myClass.GetData().push_back(2);

    for (auto it = myClass.GetData().begin(); it != myClass.GetData().end(); it++)     
    {
        //stuff
    }
}

4 个答案:

答案 0 :(得分:7)

std::vector已经有一个默认构造函数,可以正确初始化向量。什么都不做就有你想要的行为。使用memset只是具有未定义的行为。

如果要将float成员初始化为零,C ++会为此提供如下代码:

MyClass() : m_range(0) {}

C ++ 11还允许编写float m_range = 0;,但Microsoft的编译器尚未实现此功能。

mem*函数是非常粗糙的工具,在std::vector等C ++构造中没有位置。正确初始化,std::copystd::fill等替代方案是优秀的解决方案,因为它们不会践踏类型系统。

答案 1 :(得分:3)

你不应该memset构造函数的任何类对象。

答案 2 :(得分:2)

请改为:

class MyClass {
public:
    MyClass() : range{} { 

    }

    float range;
    std::vector<int> data;
};

永远不要使用memset,绝对不能使用this哦上帝。

专业提示:buy a good book

答案 3 :(得分:0)

你的对象是在memset之前构造的,它会导致问题。

以这种方式初始化对象在C ++中不是一个好方法