memset某个结构或其它的数据类型在C语言中是非常常见,其目的是对结构或数据类型进行初始化,通常都是将变量置为0。在C++中,针对类对象除了用构造函数初始化对象外,也可以使用memset来进行初始化操作。当然这种情况极其少见,即使如此还是非常有必要谈一下这个问题。
下面是一个例子:
C++语言: Codee#12885
下面是一个例子:
C++语言: Codee#12885
01
include
<
iostream
>
02
03 class Base
04 {
05 int _n;
06 public :
07 Base ( int n) : _n(n) {}
08 virtual ~ Base () {}
09 Base ( const Base & rhs) { _n = rhs . _n; }
10
11 void Show () { std :: cout << "Base::Show()" << std :: endl; }
12 virtual void Print () { std :: cout << "Base::Print()" << std :: endl; }
13 };
14
15 class Derive : public Base
16 {
17 public :
18 Derive ( int i) : Base( i) {}
19 ~ Derive () {}
20 Derive ( const Derive & rhs) : Base( rhs) {}
21
22 void Print () { std :: cout << "Derive::Print()" << std :: endl; }
23 };
24
25 int main ( void)
26 {
27 Derive * obj = new Derive( 10);
28
29 std :: cout << "Before delete ..." << std :: endl;
30 obj -> Show();
31 obj -> Print();
32
33 std :: cout << "After delete ..." << std :: endl;
34 memset ( obj , 0 , sizeof( Derive));
35 obj -> Show();
36 obj -> Print();
37
38 return 0;
39 }
编译运行结果如下:
在使用memset初始化对象Obj之前,通过Obj调用Show和Print函数时程序运行正常,但是一旦利用Memset函数初始化该对象,再对该obj调用Show和Print函数,则程序立马崩溃。 究其原因是 因为初始化obj的时候,将obj包含的指向虚函数表VTBL的指针也清除了。包含虚函数的类对象都有一个指向虚函数表的指针,此指针被用于解决运行时和动态类型强制转换时虚函数的调用问题。该指针是被隐藏的,对程序员来说,这个指针也是不可存取的。当进行memset操作时,这个指针(即指向虚函数表的地址)的值也要被初始化,这样一来,只要一调用虚函数,程序便会崩溃。
这种现象在很多由C转向C++的程序员来说,很容易犯这个错误,而且这个错误很难查。
为了避免这种情况,记住对于有虚拟函数的类对象,决不能使用memset来进行初始化操作。而是要用缺省的构造函数或其它的init例程来初始化成员变量。
02
03 class Base
04 {
05 int _n;
06 public :
07 Base ( int n) : _n(n) {}
08 virtual ~ Base () {}
09 Base ( const Base & rhs) { _n = rhs . _n; }
10
11 void Show () { std :: cout << "Base::Show()" << std :: endl; }
12 virtual void Print () { std :: cout << "Base::Print()" << std :: endl; }
13 };
14
15 class Derive : public Base
16 {
17 public :
18 Derive ( int i) : Base( i) {}
19 ~ Derive () {}
20 Derive ( const Derive & rhs) : Base( rhs) {}
21
22 void Print () { std :: cout << "Derive::Print()" << std :: endl; }
23 };
24
25 int main ( void)
26 {
27 Derive * obj = new Derive( 10);
28
29 std :: cout << "Before delete ..." << std :: endl;
30 obj -> Show();
31 obj -> Print();
32
33 std :: cout << "After delete ..." << std :: endl;
34 memset ( obj , 0 , sizeof( Derive));
35 obj -> Show();
36 obj -> Print();
37
38 return 0;
39 }
编译运行结果如下:

在使用memset初始化对象Obj之前,通过Obj调用Show和Print函数时程序运行正常,但是一旦利用Memset函数初始化该对象,再对该obj调用Show和Print函数,则程序立马崩溃。 究其原因是 因为初始化obj的时候,将obj包含的指向虚函数表VTBL的指针也清除了。包含虚函数的类对象都有一个指向虚函数表的指针,此指针被用于解决运行时和动态类型强制转换时虚函数的调用问题。该指针是被隐藏的,对程序员来说,这个指针也是不可存取的。当进行memset操作时,这个指针(即指向虚函数表的地址)的值也要被初始化,这样一来,只要一调用虚函数,程序便会崩溃。
这种现象在很多由C转向C++的程序员来说,很容易犯这个错误,而且这个错误很难查。
为了避免这种情况,记住对于有虚拟函数的类对象,决不能使用memset来进行初始化操作。而是要用缺省的构造函数或其它的init例程来初始化成员变量。