-8

Currently working on my DirectX game and using memset(0) (or ZeroMemory macro in VS if you wish) in constant buffers constructors to initialize all values with zeros and it works just fine. Problem occurs when I accidentally tried to initialize some other stuct that contains a vector this way. According to compiler (VS2010/VS2012) this causes "vector iterators incompatible", std::vector::end to be more precise. I can understand that memset might invalidate vectors iterators, but why "end" iterator is not working properly after I push back elements to the vector. Shouldn't it reposition vectors end iterator to right position (after last element)? Are all kind of std::some_container::end iterators affected by this aswell?

#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
    }
}
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261

4 Answers4

7

std::vector already has a default constructor that initializes the vector properly. Doing nothing has the behaviour you want. Using memset just has undefined behaviour.

If you want to initialize the float member to zero, C++ provides for that with code like the following:

MyClass() : m_range(0) {}

C++11 also allows writing float m_range = 0;, but Microsoft's compiler does not implement this feature yet.

The mem* functions are very crude tools that have no place among C++ constructs like std::vector. Alternatives like proper initialization, std::copy, and std::fill are superior solutions because they don't trample the type system.

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
3

You should not be memseting any objects of classes with constructors.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
2

Do this instead:

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

    }

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

Never use memset, and certainly absolutely not on this oh God.

Pro tip: buy a good book.

Community
  • 1
  • 1
0

Your object is constructed before the memset which causes problems.

Initialising an object this way is not a good approach in C++