Как скопировать указатель конструктора вектора C ++ - PullRequest
0 голосов
/ 14 ноября 2018

Я пытаюсь создать конструктор копирования для класса "Таблица" со следующими полями:

private:
    int id ;
    int capacity;
    bool open;
    std::vector<Customer*> customersList;
    std::vector<OrderPair> orderList;

Я хочу сделать глубокую копию всех полей, и я написал следующий код, и я не уверен, что сделал глубокую копию для customerList, так как это вектор указателей. Может кто-нибудь сказать мне, если я сделал глубокую или желтоватую копию? Заранее спасибо.

код:

Table(const Table& t): capacity(t.getCapacity()), open(t.isOpen()), id(t.getId()){
    std::vector<Customer*> tmp(t.customersList);
    customersList = tmp;
}

Или, может быть, я перекопировал, и я должен только сделать это? :

Table(const Table& t): customersList(t.customersList), capacity(t.getCapacity()), 
open(t.isOpen()), id(t.getId()){}

Еще раз спасибо!

Ответы [ 4 ]

0 голосов
/ 15 ноября 2018

Если вам нужен неполиморфный ответ в C ++ 98/03.Он обрабатывает то, что некоторые указатели в вашем customersList могут больше нигде не указывать.

Table(Table const &t) : id(t.id), capacity(t.capacity), open(t.open), orderList(t.orderList) {
    customersList.reserve(t.customersList.size());
    std::vector<Customer *>::const_iterator b = t.customersList.begin();
    std::vector<Customer *>::const_iterator const e = t.customersList.end();
    for (; b != e; ++b) {
        if (*b) {
            customersList.push_back(new Customer(**b));
        } else {
            customersList.resize(customersList.size() + 1);
        }
    }
}
0 голосов
/ 14 ноября 2018

Может кто-нибудь сказать мне, сделал ли я глубокую или желтоватую копию?

Вы сделали оба / или ... в зависимости от того, какой уровень косвенности вы рассматриваете.

Конструктор копирования std::vector делает глубокое копирование.То есть: вектор customersList в исходном объекте и вектор customersList в построенном объекте ссылаются на разные внутренние буферы.Если вы добавите указатель на один, он не будет автоматически отражен в другом векторе.

Однако элементы внутри вектора являются указателями.Указатели имеют одинаковые значения и указывают на одинаковые объекты Customer, а объекты Customer не были скопированы.Таким образом, копия мелкая.


Оба показанных вами предложения имеют одинаковый результат, но последний лучше, потому что он выполняет только одну операцию с вектором (построение копии), а не три (построение по умолчанию длячлен, копия конструкции местного, копия назначения участника).Если функциональность правильная, еще более простой способ добиться того же - использовать неявно сгенерированный конструктор копирования: Table(const Table& t) = default; Он делает то же самое, за исключением того, что к элементам обращаются напрямую, а не через функции-члены.

Но действительно,вам нужно тщательно продумать, что вы хотите скопировать.Вам нужны копии Customer объектов?Затем вам нужен собственный конструктор копирования, который инициализирует эти Customer объекты.Если вы это сделаете, то вам, вероятно, следует использовать вектор умных указателей, а не голые указатели (при условии, что вам вообще нужны указатели).


Я хотел создать еще один вектор, который будет содержать новыеуказатель - новое выделение памяти, но с теми же данными.Другими словами, я хочу скопировать данные в новую память и сохранить новые указатели в поле CustomersList.

В этом случае ваш конструктор копирования не будет выполнять то, что вы хотите.У вас есть новые указатели, у которых нет новых значений, и нет выделения памяти для объектов заказчика (хотя есть выделение памяти для вектора).

Как я могу это сделать?

Вы можете написать цикл, который перебирает вектор, который должен быть скопирован.Внутри цикла вы можете выделить новые объекты клиентов и скопировать инициализировать их с теми, которые указаны вектором.Затем вставьте указатель вновь выделенного указателя на конструируемый вектор-член.

Обратите внимание, что указатели в этом случае будут принадлежать.Вы никогда не должны иметь голые указатели.Для повторения: в этом случае вы должны использовать умные указатели (при условии, что вам вообще нужны указатели).

0 голосов
/ 14 ноября 2018

Нет, вы не скопировали вещи, на которые указывают эти векторные элементы.Если я правильно угадал ваше требование, вам нужно пойти дальше и сделать это «вручную»:

Table(const Table& t): capacity(t.getCapacity()), open(t.isOpen()), id(t.getId()){
    customersList.reserve(t.customersList.size());
    for (const auto old : t.customersList)
       customersList.push_back(new Customer(*old));
}

Если Customer является основой иерархии наследования, вы собираетесьнужна virtual Customer* clone() функция-член в каждом производном классе, которая делает правильные new, чтобы избежать нарезки.Если это не так, зачем вообще хранить указатели?Вместо этого сохраняйте значения и избавьте себя от всей этой проблемы.

Кстати, я надеюсь, что вы правильно управляете временем жизни этих пуанте, включая delete.В целом было бы лучше, если бы вы использовали какой-нибудь умный указатель вместо Customer*.

0 голосов
/ 14 ноября 2018

std::vector<Customer*> подразумевает, что он не владеет Customer объектами, а просто ссылается на те, что существуют в других местах.В этом случае вы можете использовать сгенерированный компилятором конструктор копирования, который выполняет для вас (мелкое) копирование для вас.Например:

Table(const Table& t) = default;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...