Шаблоны классов memcpy и C++ - как их использовать?

Итак... Как мы можем вызвать что-то вроде memcpy(dataCopy, data, length); скопировать абстрактные данные T?

Или, если абстрактный T небезопасен, скажем, мы знаем, что T - это POD (обычные старые данные, в основном структура C) - возможно ли его скопировать?


person Rella    schedule 23.01.2011    source источник
comment
Как вы хотите использовать memcpy?   -  person Etienne de Martel    schedule 23.01.2011


Ответы (3)


Вы имеете в виду работу с каким-то произвольным типом С++ T? Если вы не знаете, что T является типом POD (обычные старые данные, в основном структура C), копировать объекты типа T с memcpy небезопасно. Например, это предотвратит запуск конструктора копирования T, что может привести к неправильной копии (например, попытка memcpy и std::vector не скопирует буфер данных).

person Jeremiah Willcock    schedule 23.01.2011
comment
@Jeremiah: Означает ли это, что если у POD есть указатели, безопасно ли копировать объект с помощью memcpy? Будет ли это действительно копией исходного объекта? Что это будет за копия? - person Nawaz; 23.01.2011
comment
@Nawaz - Если у POD есть указатели, копия будет действительной (т. Е. Так же, как вы получите, используя операцию присваивания). Как и в C, копирование будет неглубоким, поэтому объекты, на которые указывают указатели, не будут скопированы. - person Jeremiah Willcock; 23.01.2011
comment
@Jeremiah: Если, по вашему мнению, такая копия безопасна, то что плохого в копировании не-POD с помощью memcpy? - person Nawaz; 23.01.2011
comment
@Nawaz - memcpy на не-POD не разрешено в соответствии со стандартом C++, в то время как выполнение этого на POD разрешено (но это происходит с ним в C, что означает неглубокую копию). Дело с std::vector было примером того, почему вам может не понадобиться поверхностная копия, поскольку копирование вектора предполагает копирование содержащихся в нем данных, а конструктор копирования сохраняет этот инвариант. - person Jeremiah Willcock; 23.01.2011
comment
@Jeremiah: Почему вы имеете в виду не разрешено в соответствии со стандартом C++? Почему это не разрешено? - person Nawaz; 23.01.2011
comment
@Jeremiah: поскольку копирование вектора должно копировать содержащиеся данные. И копирование POD с указателями не должно копировать данные, на которые указывают указатели? Действительно? - person Nawaz; 23.01.2011
comment
@Nawaz -- хотя codeidol.com/ cpp/cpp-coding-standards/ (предупреждение: сложно ориентироваться) содержит дополнительную информацию, основная причина в том, что memcpy может не сохранять инварианты классов. Помните также, что из-за членов private вы, возможно, не сможете исправить объект, такой как vector, чтобы снова удовлетворить его инварианты, и попытка сделать это в любом случае нарушает абстракцию класса. - person Jeremiah Willcock; 23.01.2011
comment
@Jeremiah: Если вы скопируете class { int a,b,c; char x,y,z; public: void f() {/*****/} }; с memcpy, какие инварианты это сломает? - person Nawaz; 23.01.2011
comment
@Nawaz - этот не нарушит никаких инвариантов и разрешен C ++ 0x (я не помню о C ++ 03). Случай, когда это было бы проблематично, - это если бы ваш класс имел нетривиальный конструктор по умолчанию, конструктор копирования и/или оператор присваивания. - person Jeremiah Willcock; 23.01.2011
comment
@Jeremiah: Так что все зависит от того, как определяется не-POD и какую копию вы хотите. В любом случае, приятно с тобой поговорить. :-) - person Nawaz; 23.01.2011
comment
@Nawaz - Если вам нужны дополнительные подробности, тривиально копируемый раздел на странице 219 open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3225.pdf объясняет точные требования C++0x. - person Jeremiah Willcock; 23.01.2011
comment
скажем, мы знаем, что T - это POD - можно ли его скопировать? - person Rella; 23.01.2011

Вы не можете сделать это надежно. Если бы это было так просто, возможно и надежно, то программисты не перегружали бы operator=() и не писали конструктор-копию.

Если вы хотите сделать копию своего объекта, то либо перегрузите operator=(), либо напишите конструктор-копию, либо сделайте и то, и другое!

person Nawaz    schedule 23.01.2011

Это может быть опасно в зависимости от типа T. Если T относится к типу POD, то все в порядке. В противном случае я предлагаю вам просто вызвать конструктор копирования T (или использовать шаблон клонирования, если это невозможно).

person Etienne de Martel    schedule 23.01.2011