Using memset or memcpy for non-POD types initialization

Question | Nov 19, 2015 | nextptr 

Unless you know what you are doing, use of memset - and its near cousins like memcpy - should be avoided for initializing non-POD types.

enter image description here

Here is an example of using memset to initialize an instance in a constructor:

struct Sample {
     Sample() { 
        memset(this, 0, sizeof(*this));
     }
     int i_;
     char c_; 
};

The above code will continue to work fine until one day you decide to add a virtual method to Sample. Adding virtual method to a class introduces a pointer to vTable, known as vptr, in its every instance. Calling memset on this would cause memory corruption because it would zero out the contents of vptr.
In general avoid using memset/memcpy for initialization if:

  • The class can be inherited or derived by other classes
  • The class contains a virtual method
  • The class contains other non-POD types

How about a question on this topic? Following is an example of a poorly written code. It uses the assignment operator and memcpy to illustrate what could go wrong.

struct A {
  A& operator = (const A& rhs) {  
      if(this != &rhs) // To avoid self-assignment
        memcpy(this, &rhs, sizeof(*this));
      return *this;
  }
  virtual void WhoAmI() = 0;
};

struct B : public A {
  B():id("B") {}
  void WhoAmI() { 
    std::cout << "In B: I am " << id << "\n"; 
  }
  const char* id;
};

struct C : public A {
   C():id("C"){}
   void WhoAmI()  {
     std::cout << "In C: I am " << id << "\n";
   }
   const char* id;
};

// Construct instances of B and C. 
// Instances of both B and C contain vptr. 
A *pB = new B();
A *pC = new C();

*pB = *pC; // Assign C to B 
pB->WhoAmI();

What would be outputted on the console?