Using memset to clear base class members
BaseStruct has no virtual member, so you should be good. vtbl should be for BaseA. However, better would be if could reset each individual member explicitly. That's recommended.
zeroing derived struct using memset
This assumes that the Base
base class subobject is located at the beginning of Derived
. This won't work if you add another base class.
Further, your code is wrong: pointer arithmetic is performed in terms of objects, not in terms of bytes. You need to use reinterpret_cast<char*>(this)
to perform the arithmetic in terms of bytes. In any case, you still shouldn't do this.
Consider the following, non-ugly, standards-conforming approach utilizing value initialization:
struct Derived : public Base
{
struct DerivedMembers { /* ... */ }
DerivedMembers data;
Derived() : data() { }
};
As long as DerivedMembers
has no constructor, this will value initialize each of the data members of data
, which look like it's exactly the behavior you want.
Or, if you want the members to be accessible without using a "data
" member variable, consider using another base class:
struct DerivedMembers { /* ... */ }
struct Derived : Base, DerivedMembers
{
Derived() : DerivedMembers() { }
};
Should C++ programmer avoid memset?
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.
C memset seems to not write to every member
No don't use memset
-- it zeroes out the size of a pointer (4 bytes on my x86 Intel machine) bytes starting at the location pointed by this
. This is a bad habit: you will also zero out virtual pointers and pointers to virtual bases when using memset
with a complex class. Instead do:
template <class T>
class vector2
{
public:
// use initializer lists
vector2() : x(0), y(0) {}
T x;
T y;
};
in c++11, can you always (safely) replace a memset() initialization with an empty initializer?
You can certainly initialize any standard layout type using empty parenthesis and get it zero initialized. Once you add constructors into the picture, this isn't necessarily true, unfortunately:
struct foo {
int f;
};
struct bar {
int b;
bar() {}
};
foo f{};
bar b{};
While f.f
is zero initialized, b.b
is uninitialized. However, there isn't anything you can do about bar
because you can't memset()
it either. It needs to be fixed.
C++: Fastest way to initialize class object to 0
There is no "magic" syntax to achieves this.
If the class has no virtual table, you could use memset(this, 0, sizeof(* this))
, but it is not recommended.
You could try to play with offsetof
to pinpoint the address of the first member, and erase from there on. This is a bit better than simply memset
ing the whole thing, but it is still making me uncomfortable:
// Example non-POD type.
class B
{
public:
B() : b(0xDEADBEEF) {}
int b;
};
class Monstrosity
{
public:
Monstrosity()
{
size_t offset = offsetof(Monstrosity, a);
uint8_t *eraseStart = (uint8_t *)this + offset;
memset(eraseStart, 0, sizeof(Monstrosity) - offset);
}
virtual int foo() { return 0; }
int a;
B b;
};
If any if your members has a virtual table, you're practically screwed.
Related Topics
Initializer List Not Working with Vector in Visual Studio 2012
Cyclic Dependency Between Header Files
Calling a Virtual Function from the Constructor
Clean C++ Granular Friend Equivalent? (Answer: Attorney-Client Idiom)
Error Lnk2005: Xxx Already Defined in Msvcrt.Lib(Msvcr100.Dll) C:\Something\Libcmt.Lib(Setlocal.Obj)
How to Link a Plain File into My Executable
Determining Exception Type After the Exception Is Caught
Invalid Use of Incomplete Type
Delayed Start of a Thread in C++ 11
How to Cast a Derived Class to a Private Base Class, Using C-Style Cast
Rotate an Image in C++ Without Using Opencv Functions
How to Convert from Int to Char*
At What Point Is It Worth Using a Database
Practical Uses for the "Curiously Recurring Template Pattern"