Как скопировать структуру с указателями на данные внутри (чтобы скопировать указатели и данные, на которые они указывают)? - PullRequest
3 голосов
/ 31 января 2011

поэтому у меня есть такая структура, как

struct GetResultStructure
{
  int length;
  char* ptr;
};

Мне нужен способ сделать полную копию, что означает, что мне нужна копия, чтобы иметь структуру с новым ptr-указанием на копию данных, которые у меня были воригинальная структура.Это как-нибудь возможно?Я имею в виду, что любая имеющаяся у меня структура, содержащая ptrs, будет иметь несколько полей со своей длиной. Мне нужна функция, которая скопировала бы мою структуру, копируя все ptrs и данные, на которые они указывают, с помощью данного массива длин ... Любая классная функция повышения для этого?Или как создать такую ​​функцию?

Ответы [ 5 ]

7 голосов
/ 31 января 2011

Для описанного вами конкретного сценария используйте std::vector или какой-либо другой контейнер последовательности.Если вы это сделаете, то простое копирование объектов типа GetResultStructure также сделает копии указанных данных:

struct GetResultStructure {
    std::vector<char> data;
};

GetResultStructure a = GetData();
GetResultStructure b = a; // a and b have distinct, equivalent data vectors

В общем, когда вам нужно реализовать это самостоятельно, вы делаетепутем реализации конструктора копирования и оператора присваивания копии.Самый простой способ сделать это - использовать идиому копирования и замены, подробно описанную в Что такое идиома копирования и замены?

2 голосов
/ 31 января 2011

Должны быть реализованы как конструктор копирования, так и оператор присваивания (как указано выше). Однако метод, который может помочь в этом процессе, использует оператор разыменования (*) при копировании данных указателя. Это скопирует данные указателя, а не места памяти. Если вы сделаете ptr1 = ptr2, он просто устанавливает ячейку памяти ptr1 в ptr2, поэтому мы обращаемся к ней.

Например, я просто покажу краткий пример конструктора копирования:

GetResultStructure(const GetResultStructure& other)
    : length(other.length), ptr(new char[length]) // <--- VERY _important_ - initialization of pointer
{
    // Alternatively, put your initialization here like so:
    // ptr = new char[length];
    for(int i=0;i<length;++i)
    {
        ptr[i]  = new char;
        *ptr[i] = *other.ptr[i]; // Copy the values - not the memory locations
    }
}

И затем, очевидно, обязательно очистите свой деструктор, чтобы предотвратить утечки памяти.

С уважением,
Деннис М.

2 голосов
/ 31 января 2011

Это в значительной степени зависит от вас, чтобы реализовать это. Обычно вы хотите сделать это как конструктор копирования, поэтому вам нужно сделать это только в одном месте. К сожалению, нет никакой реальной магии, чтобы не сообщать компьютеру о том, как копировать вашу структуру.

Конечно, это применимо, только если ваша структура действительно существенно отличается от того, что уже написано. Тот, который вы дали, выглядит лот как строка или (возможно) вектор. Если вам действительно не нужно реализовывать что-то новое, вам, вероятно, лучше использовать один из тех, которые уже предоставлены.

1 голос
/ 31 января 2011

Поскольку вы пометили его как C ++: напишите конструктор копирования и оператор присваивания , в котором вы реализуете код глубокого копирования:

struct GetResultStructure
{
    GetResultStructure(const GetResultStructure& other)
    {
        // Deep copy code in here   
    }
    GetResultStructure& operator=(const GetResultStructure& other)
    {
        if (this != &other) {
            // Deep copy code in here
        }
        return *this
    }
    int length;
    char* ptr;
};
1 голос
/ 31 января 2011
GetResultStructure doCopy(GetResultStructure const& copy) {
  GetResultStructure newstruct;
  newstruct.length = copy.length;
  newstruct.ptr = new char[newstruct.length];
  memcpy(newstruct.ptr, copy.ptr, newstruct.length*sizeof(char));
  return newstruct;
}

Должно быть просто. Да, sizeof (char) на самом деле не нужен, но там показано, что делать для других типов данных.

...