2016-01-08 3 views
1

У меня есть структура определяется следующим образом:Копирования структуры на другую структуру

struct Queries { 

    uint64_t Id; 
    uint64_t from; 
    uint32_t counter; // total queries 
    char queries[]; 
}; 

То, что я пытаюсь сделать, это создать новый STRUCT «объект» и скопировать значения из существующего в этом новом объект.

То, что я пытался

void function(Queries* oldq){ 

    Queries* q = new Queries(); 

    // values are copied correctly 
    q->Id = oldq->Id; 
    q->from = oldq->from; 
    q->counter = oldq->counter; 

    // copy is not correct 
    for (unsinged i = 0; i < oldq->counter; i++) 
      q->queries[i] = oldq->queries[i]; 

} 

1) Я также попытался:

q = oldq; 

, но это не работает.

2) Я думаю, что мне нужно выделить пространство для массива запросов, но поскольку член структуры не является указателем, я не знаю, как это сделать.

+2

Если вы определяете правильную копию ctor, вы можете использовать 'Queries * q = new Queries (* oldq);' – Slava

+0

Ваше мышление верное. Перед копированием массива необходимо предварительно выделить 'counter * sizeof (char)' bytes. Но вам не нужен явный цикл для его копирования - вы можете использовать 'memcpy'. В качестве альтернативы вы можете реализовать это как [конструктор копирования] (http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three), как цитируется Slava. – jweyrich

+0

Но как мне выполнить назначение в массиве внутри конструктора копирования? – pirox22

ответ

2

Здесь вы имеете дело с C-style flexible array member. Это недопустимый код C++, но он действителен с C99 (см. Ссылку для подробностей). Чтобы использовать такую ​​структуру, вам нужно выделить sizeof(Queries) + counter байт, где поле массива будет использовать эту часть counter. (Примечание: если у вас есть поле массива, отличное от char, вам придется умножать соответственно.)

Теперь вы не можете использовать функции C++ здесь как конструктор копирования, так как компилятор не знает размер вашей структуры. Вместо этого, вы должны использовать чистый C подход:

Queries *cloneQueries(Queries *oldQ) 
{ 
    size_t sizeQ = sizeof(Queries) + oldQ->counter; 
    Queries *newQ = (Queries*)malloc(sizeQ); 
    memcpy(newQ, oldQ, sizeQ); 
    return newQ; 
} 
+0

Это сработало !!! Спасибо ! – pirox22

2

Проще всего сделать это, чтобы использовать std::string для queries.

Тогда вы можете просто написать Queries* q = new Queries(*oldq); и полагаться на , созданный компилятором. constructor: вы можете удалить весь свой код копирования.

1

Вы можете сделать это с помощью copy constructor, который выполняет глубокую копию вашего объекта.

Это может быть сделано, когда вместо function() вы определяете конструктор копирования, как так:

Queries(const Queries& q) 
    : Id(q.Id), from(q.from), counter(q.counter) 
{ 
    // allocate the new memory 
    queries = new char[counter]; 

    // copy each element 
    for (size_t i = 0; i < counter; ++i) { 
     queries[i] = q.queries[i]; 
    } 
} 

, а затем в вашем коде, вы можете использовать следующую строку:

Queries *q = new Queries(*oldq); 

где объект на правая сторона создается путем создания копии, то есть путем копирования объекта oldq.


См., how operator new[] works.

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