我正在尝试为具有以下字段的“ 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()){}
再次感谢!
答案 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*
,通常会更好。