如上所述,newcustomer.clear()将清空向量,但它不会处理指针。HadeS在他或她的解决方案中解决了这个问题。以下是几种解决问题的方法。
与某些语言不同,在C++中,我们不必使用new
创建指针。这种方法丢弃指针并直接将Customer存储在向量中。这通常是最安全的解决方案,因为您必须努力使此解决方案出错。
int main()
{
vector<Customer> newcustomer;
newcustomer.push_back(Customer("III", 123333, 555));
newcustomer.push_back(Customer("LOL", 122222, 444));
newcustomer.push_back(Customer("PPL", 121111, 333));
newcustomer.clear();
return 0;
}
这有点笨重。你创建了一个临时的Customer(调用构造函数),并将其复制到向量中(调用复制构造函数)。通过在Customer构造函数和析构函数中添加适当的调试语句,你最终得到像这样的垃圾:
create III
copy III
destroy III
create LOL
copy LOL
copy III
destroy III
destroy LOL
create PPL
copy PPL
copy III
copy LOL
destroy III
destroy LOL
destroy PPL
Use III
Use LOL
Use PPL
destroy III
destroy LOL
destroy PPL
创建3个,复制6份,销毁9个。
如果Customer由指针或复杂的自定义数据类型组成,那么很可能需要定义复制构造函数来使其正常工作。参见Rule Of Three。
C++11有一种不那么繁琐的方法:
int main()
{
vector<Customer> newcustomer;
newcustomer.emplace_back("III", 123333, 555);
newcustomer.emplace_back("LOL", 122222, 444);
newcustomer.emplace_back("PPL", 121111, 333);
newcustomer.clear();
return 0;
}
消除了第一个版本中的一些工作。输出看起来像这样:
create III
create LOL
copy III
destroy III
create PPL
copy III
copy LOL
destroy III
destroy LOL
Use III
Use LOL
Use PPL
destroy III
destroy LOL
destroy PPL
3 创建,3 复制,6 销毁。
如果客户端有移动构造函数,则输出如下:
create III
create LOL
move III
destroy
create PPL
move III
move LOL
destroy
destroy
Use III
Use LOL
Use PPL
destroy III
destroy LOL
destroy PPL
3 创建,3 移动,6 销毁。
如果 Customer 复制需要很长时间或使用了大量 RAM,那么实现移动构造函数是值得的,因为您不想临时复制大量 RAM。但是,如果您使用了大量 RAM,通常复制将需要很长时间。
重要提示:看到有一堆没有说明它们是谁的“销毁”吗?这是因为移动构造函数从源移动数据到目标。源不再具有任何数据。移动构造函数不能使源处于这样的状态,即如果在移动后使用源,则会出现未定义行为。欢迎来到五法则。
如果出于某种原因必须使用指针,则将它们包装在智能指针中可以使内存管理变得更加容易。例如:
int main()
{
vector<unique_ptr<Customer>> newcustomer;
newcustomer.emplace_back(new Customer("III", 123333, 555));
newcustomer.emplace_back(new Customer("LOL", 122222, 444));
newcustomer.emplace_back(new Customer("PPL", 121111, 333));
newcustomer.clear();
return 0;
}
这个输出看起来非常棒:
create III
create LOL
create PPL
Use III
Use LOL
Use PPL
destroy III
destroy LOL
destroy PPL
但是没有显示的是unique_ptrs被创建、移动和销毁的速率与前面示例中的Customers相同。根据Customer的移动构造函数的成本,您可能会节省一些时间或精力,也可能不会。
std::unique_ptr
并忘记所有细节。或者,如果需要,可以使用std::shared_ptr
。 - Nik Bougalis