简体   繁体   English

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

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

I have a Class that inherit from a list of pointers, example:我有一个从指针列表继承的 Class,例如:

Class C : protected list<Type*>

Now, i want to overload the operator= (and to write the copy constructor).现在,我想重载 operator= (并编写复制构造函数)。 Should i iterate the list making a new Type for each pointer inside the list?我应该迭代列表,为列表中的每个指针创建一个新类型吗?

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

or can i do this?或者我可以这样做吗?

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

I've edited my answer, as this is a homework exercise我已经编辑了我的答案,因为这是一个家庭作业

In a normal application you shouldn't derive from a STL container, their destructors are not virtual.在普通应用程序中,您不应从 STL 容器派生,它们的析构函数不是虚拟的。 Thus when C is destroyed, the std::list<T> will remain, causing a memory leak.因此,当C被销毁时, std::list<T>将保留,从而导致 memory 泄漏。 They are not meant to be inherited form in the first place...它们一开始并不意味着继承形式......

In a normal design, you would have the list as an object:在正常设计中,您会将列表作为 object:

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

What I would consider a GOOD exercise is that you implement a MyList class, making everything from scratch.我认为一个好的练习是你实现了一个MyList class,一切从头开始。 But it is common knowledge that professors make student do weird illogical stuff.但众所周知,教授让学生做奇怪的不合逻辑的事情。 So lets assume you indeed want to derive from std::list and only overload operator= , doing the copy yourself因此,假设您确实想从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;
    }
};

Now, how do you copy... many flavors: There's the good-old C-style loop:现在,你如何复制......多种口味:有古老的 C 风格循环:

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

There's the iterator loop:有迭代器循环:

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

There's the iterator loop with auto and generalized accessors:有带有auto和通用访问器的迭代器循环:

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

There's range-based for loops:有基于范围的 for 循环:

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

There's algorithms, like std::for_each有算法,比如std::for_each

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

... and std::copy ...和std::copy

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

note that std::back_inserter is an iterator that performs a push_back while iterating.请注意, std::back_inserter是一个迭代器,它在迭代时执行push_back

And in the future (C++20) we will have ranges, so you can write something like并且在未来(C++20)我们将有范围,所以你可以写类似的东西

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

Although I'm not sure that's correct...虽然我不确定这是否正确...

Choose your poison!选择你的毒药!

It depends what you want to do!这取决于你想做什么!

The first performs a deep copy ;第一个执行深拷贝 the second just performs a shallow copy of the pointers in the list, and thus does nothing that the original std::list implementation didn't do.第二个只是执行列表中指针的浅拷贝,因此没有做原始std::list实现没有做的事情。

Also, if(!(*this)==c)) is wrong;另外, if(!(*this)==c))是错误的; it has too many ) and was probably intended to be if (this != &c) .它有太多)并且可能打算是if (this != &c)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM