Була тільки що невеличка дискусія з Борисом з приводу застосування memcpy для ініціалізації членів класу у об'єкті. Всі пишуть про те що memcpy неможна використовувати для non-POD типів даних. А non-POD нам дає, як мінімум, наявність деструктора чи оператора operator=.
Дискусія затягнулась, тому довелось застосувати зброю масового знищення - прямий експеримент.
Джерельні коди:
gdb (перед виводом на консоль):
Тут для мене повна несподіванка - вказівник один а адреси різні!
Ага! Таблиця віртуальних методів за зміщенням 0 у кількості 1 елемент!
У B2 віртуальних методів немає, тому таблиці теж немає і адреса c співпадає з адресою B2.
Таким чином, memcpy таки можна використовувати... доки у вас немає віртуальних методів. Щодо оператора operator= я не перевіряв, а от деструктор перевірив.
Якщо деструктор не віртуальний - ніяких проблем. Але при наявному наслідуванні деструктор рекомендують робити віртуальним (Я думаю, всім зрозуміло чому). Таким чином виникає віртуальний метод, vtable і неможливість використовувати memcpy.
Дискусія затягнулась, тому довелось застосувати зброю масового знищення - прямий експеримент.
Джерельні коди:
#include <cstdlib>
#include <iostream>
using namespace std;
class B1 {
public:
int a;
int b;
int x;
virtual void y();
};
void B1::y()
{
a = b;
}
class B2 {
public:
int c;
int d;
};
class D : public B1, public B2 {
};
int main (int argc, char** argv){
D dd;
B1 * b1;
B2 * b2;
dd.a = 0;
dd.b = 1;
dd.c = 2;
dd.d = 3;
b1 = ⅆ
b2 = ⅆ
int a, b, c, d, x;
a = b1->a;
b = b1->b;
c = b2->c;
d = b2->d;
x = b1->x;
cout << a << ", " << b << ", " << c << ", " << d << ", " << x << endl;
return EXIT_SUCCESS;
}
|
| _Winnie C++ Colorizer |
gdb (перед виводом на консоль):
(gdb) print &dd $1 = (D *) 0xbfbd5e40 (gdb) print b1 $2 = (D *) 0xbfbd5e40 (gdb) print b2 $3 = (B2 *) 0xbfbd5e50
Тут для мене повна несподіванка - вказівник один а адреси різні!
(gdb) print &b1->a $4 = (int *) 0xbfbd5e44
Ага! Таблиця віртуальних методів за зміщенням 0 у кількості 1 елемент!
(gdb) print &b2->c $5 = (int *) 0xbfbd5e50
У B2 віртуальних методів немає, тому таблиці теж немає і адреса c співпадає з адресою B2.
Таким чином, memcpy таки можна використовувати... доки у вас немає віртуальних методів. Щодо оператора operator= я не перевіряв, а от деструктор перевірив.
Якщо деструктор не віртуальний - ніяких проблем. Але при наявному наслідуванні деструктор рекомендують робити віртуальним (Я думаю, всім зрозуміло чому). Таким чином виникає віртуальний метод, vtable і неможливість використовувати memcpy.