I heard a saying that c++ programmers should avoid memset,
class ArrInit {
//! int a[1024] = { 0 };
int a[1024];
public:
ArrInit() { memset(a, 0
In C++ you should use new. In the case with simple arrays like in your example there is no real problem with using it. However, if you had an array of classes and used memset to initialize it, you woudn't be constructing the classes properly.
Consider this:
class A {
int i;
A() : i(5) {}
}
int main() {
A a[10];
memset (a, 0, 10 * sizeof (A));
}
The constructor for each of those elements will not be called, so the member variable i will not be set to 5. If you used new instead:
A a = new A[10];
than each element in the array will have its constructor called and i will be set to 5.
This is an OLD thread, but here's an interesting twist:
class myclass
{
virtual void somefunc();
};
myclass onemyclass;
memset(&onemyclass,0,sizeof(myclass));
works PERFECTLY well!
However,
myclass *myptr;
myptr=&onemyclass;
memset(myptr,0,sizeof(myclass));
indeed sets the virtuals (i.e somefunc() above) to NULL.
Given that memset is drastically faster than setting to 0 each and every member in a large class, I've been doing the first memset above for ages and never had a problem.
So the really interesting question is how come it works? I suppose that the compiler actually starts to set the zero's BEYOND the virtual table... any idea?
The issue is not so much using memset() on the built-in types, it is using them on class (aka non-POD) types. Doing so will almost always do the wrong thing and frequently do the fatal thing - it may, for example, trample over a virtual function table pointer.
It is "bad" because you are not implementing your intent.
Your intent is to set each value in the array to zero and what you have programmed is setting an area of raw memory to zero. Yes, the two things have the same effect but it's clearer to simply write code to zero each element.
Also, it's likely no more efficient.
class ArrInit
{
public:
ArrInit();
private:
int a[1024];
};
ArrInit::ArrInit()
{
for(int i = 0; i < 1024; ++i) {
a[i] = 0;
}
}
int main()
{
ArrInit a;
}
Compiling this with visual c++ 2008 32 bit with optimisations turned on compiles the loop to -
; Line 12
xor eax, eax
mov ecx, 1024 ; 00000400H
mov edi, edx
rep stosd
Which is pretty much exactly what the memset would likely compile to anyway. But if you use memset there is no scope for the compiler to perform further optimisations, whereas by writing your intent it's possible that the compiler could perform further optimisations, for example noticing that each element is later set to something else before it is used so the initialisation can be optimised out, which it likely couldn't do nearly as easily if you had used memset.
There's no real reason to not use it except for the few cases people pointed out that no one would use anyway, but there's no real benefit to using it either unless you are filling memguards or something.
In C++ std::fill
or std::fill_n
may be a better choice, because it is generic and therefore can operate on objects as well as PODs. However, memset
operates on a raw sequence of bytes, and should therefore never be used to initialize non-PODs. Regardless, optimized implementations of std::fill
may internally use specialization to call memset
if the type is a POD.