如何复制构造函数指针向量C ++

时间:2018-11-14 17:41:12

标签: c++ c++11 pointers vector copy-constructor

我正在尝试为具有以下字段的“ Table”类创建副本构造函数:

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

我想对所有字段进行深层复制,并编写了以下代码,但由于其指针矢量,我不确定我对customersList进行了深层复制。有人可以告诉我是否制作了深拷贝或浅拷贝?预先谢谢你。

代码:

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 :(得分:2)

  

有人可以告诉我我做的是深拷贝还是浅拷贝?

您做出的两种选择都取决于您正在考虑的间接级别。

std::vector的副本构造函数执行深层副本。即:原始对象中的向量customersList和构造对象中的向量customersList引用了不同的内部缓冲区。如果您将指针添加到一个,则它不会自动反映在另一个向量中。

但是,向量内部的元素是指针。指针具有相同的值,并且指向相同的Customer对象,并且没有复制任何Customer对象。因此副本很浅。


您显示的两个建议都具有相同的结果,但后者更好,因为它只对向量执行一个操作(复制构造),而不是对三个进行操作(成员的默认构造,本地的复制构造,成员的复制分配)。如果功能正确,则更简单的方法是使用隐式生成的副本构造函数:Table(const Table& t) = default;相同,除了直接访问成员而不是通过成员函数访问。

但是实际上,您需要考虑要复制的内容。您是否需要Customer对象的副本?然后,您确实需要一个自定义副本构造函数,该构造函数将这些Customer对象进行复制初始化。如果这样做,那么您可能应该使用智能指针的向量,而不是裸指针(假设您根本需要指针)。


  

我想创建另一个包含新指针的向量-新的内存分配,但具有相同的数据。换句话说,我想将数据复制到新的内存中,并将新的指针保存在customersList字段中。

在这种情况下,您的副本构造函数无法执行您想要的操作。您有新的指针,这些指针没有新的值,也没有为客户对象分配内存(尽管向量有内存分配)。

  

我该怎么做?

您可以编写一个循环,该循环遍历要复制的向量。在循环中,您可以分配新的客户对象,并使用矢量所指向的对象进行复制初始化。然后将新分配的指针插入正在构造的成员向量中。

请注意,在这种情况下,指针将归所有者所有。您永远不应该拥有裸露的指针。要再次重申:在这种情况下,您应该使用智能指针(假设您根本需要指针)。

答案 1 :(得分:0)

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

答案 2 :(得分:-1)

std::vector<Customer*>表示它不拥有Customer对象,仅引用存在于其他位置的对象。在这种情况下,您可以使用编译器生成的副本构造函数,该构造函数为您执行成员级(浅)复制。例如:

Table(const Table& t) = default;

答案 3 :(得分:-1)

否,您尚未复制这些矢量元素所指向的内容。如果我正确地猜到了您的要求,则需要继续进行“手动”操作:

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成员函数,以避免切片。如果不是,为什么还要存储指针呢?而是存储值并为您自己避免整个麻烦。

顺便说一句,我希望您能适当地管理这些Pointpoint的生命周期,包括delete。总体而言,如果您使用某种智能指针而不是Customer*,通常会更好。