Копировать конструктор или оператор перегрузки с унаследованным списком указателей - PullRequest
0 голосов
/ 02 ноября 2019

У меня есть класс, который наследуется от списка указателей, например:

Class C : protected list<Type*>

Теперь я хочу перегрузить оператор = (и написать конструктор копирования). Должен ли я повторять список, создавая новый тип для каждого указателя внутри списка?

void C::operator=(const C& c)
{
    if(!(*this)==c))
    {
        clear();
        for(list<Type*>::iterator it = c.begin(); it != c.end(); it++)
        {
           Type* cp = new Type((*it)); //or doing cp=&(*it) after the new
           push_back(cp);
        }
    }
}

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

void C::operator=(const C& c)
{
    if(!(*this)==c))
    {
        clear();
        for(list<Type*>::iterator it = c.begin(); it != c.end(); it++)
        {
           Type* cp = it; //or cp=&(*it)
           push_back(cp);
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 02 ноября 2019

Зависит от того, что вы хотите сделать!

Первый выполняет глубокое копирование ;второй просто выполняет поверхностную копию указателей в списке и, таким образом, ничего не делает, чего не делала оригинальная реализация std::list.

Кроме того, if(!(*this)==c)) неверно;у него слишком много ) и, вероятно, он должен был быть if (this != &c).

0 голосов
/ 02 ноября 2019

Я отредактировал свой ответ, так как это домашнее задание

В обычном приложении вы не должны получать данные из контейнера STL, их деструкторы не являются виртуальными. Таким образом, когда C будет уничтожено, std::list<T> останется, что приведет к утечке памяти. Во-первых, они не предназначены для унаследованной формы ...

В обычном проекте список будет представлен в виде объекта:

#include <list>

template<typename T>
class C {
private:
    std::list<T*> lst;
public:
    C& operator=(const C& c) {
        if (this != &c) {
            lst = c.lst;
        }
        return *this;
    }
};

Что я бы назвал ХОРОШЕЕ упражнение состоит в том, что вы реализуете MyList класс, делая все с нуля. Но общеизвестно, что профессора заставляют студентов делать странные нелогичные вещи. Итак, давайте предположим, что вы действительно хотите извлечь из std::list и только перегрузить operator=, делая копию самостоятельно

#include <list>

template<typename T> 
class C : protected std::list<T*>
{
public:
    constexpr C& operator=(C const& c) noexcept {
        if (this != &c) {
            this->clear();
            // copy
        }
        return *this;
    }
};

Теперь, как вы копируете ... множество ароматов! Есть старый добрый цикл в стиле C:

for (int i = 0; i < c.size(); ++i) this->push_back(c[i]);

Есть цикл итератора:

for (std::list<T*>::const_iterator it = c.cbegin(); it != c.cend(); ++it) this->push_back(*it);

Есть цикл итератора с auto и обобщенными средствами доступа:

for (auto it = std::cbegin(c); it != std::cend(c); ++it) this->push_back(*it);

Для циклов есть диапазон:

for (auto const& el : c) this->push_back(el);

Есть алгоритмы, такие как std::for_each

std::for_each(std::cbegin(c), std::cend(c), [this](T* ptr) { this->push_back(ptr); });

... и std::copy

std::copy(std::cbegin(c), std::cend(c), std::back_inserter(*this));

обратите внимание, что std::back_inserter - это итератор, который выполняет push_back во время итерации.

И в будущем (C ++ 20) у нас будут диапазоны, поэтому вы можете написать что-то вроде

std::ranges::copy(c, *this);

Хотя я не уверен, что это правильно ...

Выбери свой яд!

...