使用继承的指针列表复制构造函数或重载 Operator=

Copy Constructor or overloading Operator= with an inherited list of pointers

我有一个继承自指针列表的 Class,例如:

Class C : protected list<Type*>

现在,我想重载 operator=(并编写复制构造函数)。我应该迭代列表为列表中的每个指针创建一个新类型吗?

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);
        }
    }
}

我已经编辑了我的答案,因为这是作业练习

在正常的应用程序中,您不应从 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;
    }
};

我认为 GOOD 练习是您实施 MyList class,使 一切从头开始。 但众所周知,教授会让学生做一些奇怪的不合逻辑的事情。所以让我们假设你确实想从 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 循环:

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);

虽然我不确定这是否正确...

选择你的毒药!

这取决于你想做什么!

第一个执行深拷贝;第二个只是执行列表中指针的浅拷贝,因此没有做原始 std::list 实现没有做的任何事情。

还有,if(!(*this)==c))是错误的;它有太多 ) 并且可能是 if (this != &c).