2012-06-27 2 views
0

Прям назначение (т.е.=) такой же, как кастинг-то char*, а затем, используя for цикл, чтобы скопировать его байт за байтом? *
Я хочу знать, есть ли преимущество одного метода над другим.для цикла против оператора присваивания

struct A 
{ 
    int a; 
    int b; 
} Test; 

void* Buffer = malloc(1024); 


// Casting and byte copying 
for (int i=0; i != 8; i++) 
{ 
    ((char*)Buffer)[i] = ((char*)Test)[i]; 
} 

// Assignment 
((A*)Buffer)[0] = Test; 

* все типы побитовое копируемыми.

EDIT: на основе ответов, является memcopy такой же, как '='

+6

Почему бы не использовать memcpy? –

+2

Theres so many ifs, maybes и somtimeses ... просто используйте оператор =. Да, он побито копирует _ в ваш случай_, но что, если в структуре не было 8 байтов?/ –

ответ

10

Это в основном то, что memcpy делает, и действует в течение POD types (предполагается, что на самом деле sizeof(Test) 8). Тем не менее, memcpy почти наверняка будет быстрее, потому что у компилятора будут специальные оптимизированные ассемблерные подпрограммы.

Вы будете вызывать неопределенное поведение, если вы попробуете это (или memcpy) с не-POD-типом. Поэтому, в общем, вы должны использовать std::copy или просто использовать назначение.

Вы также должны избегать malloc в C++, поскольку он не является безопасным для типов; используйте new, или placement new если вам нужно.

+0

, каждый, входящий в буфер, является POD или массивом POD. – Lauer

+1

@ user1204406: тогда ручное копирование безопасно. Но это также бессмысленно, возможно, медленнее и труднее читать/поддерживать, чем простой '='. –

+0

theres время, когда мне нужно разложить один объект на 2 буфера. поэтому ручное копирование является nessacary. но иногда он поступает только в один буфер, поэтому '=' работает там. должен ли я сделать специальный случай, если я могу поместить его или просто придерживаться цикла for, чтобы быть последовательным? – Lauer

1

Прежде всего, это не C++. Это уродливое C. Вы вручную выделяете блок памяти размером 1024 байта, фиксируя его адрес голым указателем. Кроме того, в образце кода вы никогда не освобождаете его, утечка MB памяти. Это считается крайне плохой практикой, когда дело доходит до C++.

C++ не является C с классами, это прекрасный язык, который может выражать себя, используя его в сочетании со стандартной библиотекой и придерживаясь лучших шаблонов проектирования, которые естественным образом реализуются при программировании OO, особенно с понятиями RAII, общего инкапсуляция, которая может привести к лучшему управлению памятью. Даже new уклоняется от необходимости, не говоря уже о malloc.

for (int i=0; i != 8; i++) 

Также вы делаете опасные предположения, что может привести к неопределенному поведению.

((char*)Buffer)[i] = ((char*)Test)[i]; 

Я даже не собираюсь комментировать это. Святой ... Не только это плохо, это не работает. Вы пытаетесь заставить экземпляр structA, лежащий на стеке, обычный «объект»/var, в char*. Вам не хватает &Test.

Используйте memcpy, если вы используете этот путь, но, пожалуйста, подумайте об улучшении вашего подхода на C++. memcpy принимает три аргумента, назначение, источник и размер в байтах. Удостоверьтесь, что они совпали, и вы получите быструю копию за каждый байт.

+0

: не могут отправлять указатели через TCP. ЧАСТЬ этого загружает классы w/указатели в буфер, чтобы их можно было портировать.поэтому мне нужен блок памяти, который может хранить данные класса и массивы внутри (выделено динамически). И нет, я не собираюсь освобождать что-то, что будет повторно использоваться, это менее эффективно. – Lauer

0

приписывание, используя оператор =, определенно не то же как for цикла копирования байт. Оператор = уважает тип, , и то, что он делает, будет зависеть от типа.И копирование байта байтом - неопределенное поведение в большинстве случаев. В вашем конкретном случае я бы ожидал, что компилятор сгенерирует что-то эквивалентное обработке данных в виде unsigned long long и копирует это, используя только одну или две инструкции машины . Но это только из-за особенностей типа, который вы определили. В общем, дайте компилятору столько информации , сколько сможете, и доверьтесь ему; это, как правило, делает лучшую работу, что вы можете.

+0

прочитал ответ Оли и комментарии, есть два буфера, поэтому мне нужно разбить структуру на более мелкие типы. – Lauer

0

Это не прямой ответ на вопрос OP, но вместо этого это ответ на то, что я думаю, что он пытается достичь.

Запись форматированных данных в передаваемый формат serialization и на C++ существует несколько способов сделать это. Есть несколько вещей, которые следует учитывать: должен ли формат быть ascii, xml, двоичный, а в случае двоичного - быть кроссплатформенным (endianess, alignment). В любом случае наивный способ копирования структур в байтовый буфер почти никогда не требуется.

Вы можете рассмотреть следующие варианты:

  • , когда это может быть в формате ASCII, самый простой способ заключается в использовании iostreams
  • boost.serialization
  • внешних библиотек (достаточно справедливой: повышение также один) : росы, протокол буфера Google, ...
  • прокатки самостоятельно (на основе преобразования примитивов)

см. Также this question

+0

Хит гвоздь на голове. Я хотел бы написать его сам, хотя я больше узнаю. – Lauer

+0

Выполняя это самостоятельно, стоит ли использовать специальный случай «=»? – Lauer

+0

Нет, если вы хотите перегрузить оператора, используйте оператор << для потока в ваш буферный поток, поэтому он похож на потоковое на std :: cout – stefaanv

Смежные вопросы