向量复制构造函数C++:它必须是线性时间吗

vector copy constructor C++ : does it have to be linear time?

本文关键字:线性 时间 复制 构造函数 C++ 向量      更新时间:2023-10-16

我有一个包含STL映射类型对象的向量,我做vector.push_back(some map)

不幸的是,这会调用映射副本构造函数,并浪费大量时间。我知道我可以通过保留一个指向映射的(智能)指针向量来解决这个问题,但这让我想知道——我读到STL无论如何都会将其数据保存在堆上,而不是堆栈上——那么为什么复制ctor不是O(1)时间,只需复制指针?

如果在将副本推回向量后不再需要原始映射,请写入:

some_vector.push_back(std::move(some_map));

如果您还没有C++11编译器,请添加一个空映射,然后将其与原始映射进行交换:

some_vector.resize(some_vector.size() + 1);
some_vector.back().swap(some_map);

要直接回答您的问题:要做到这一点,必须从某种写时复制机制开始——当您将某个东西放入向量中时,它必须是原始文件的副本(或者至少表现得像一个)。例如,如果我将地图推到向量上,然后从原始地图中删除一个项目,那么该项目应该仍然存在于推到向量的地图副本中。

然后,它必须跟踪所有指针,并确保指针对象(在本例中为映射)保持有效,直到所有指针本身都被销毁。这样做当然是可能的。例如,相当多的语言提供垃圾收集主要是出于这个原因。其中大多数都会改变事物的语义,因此当/如果你(例如)创建一个地图向量时,将地图放入向量中具有引用语义——也就是说,当你修改原始地图时,应该会改变你放入其他集合的任何"副本"。

正如您所观察到的,如果您真的愿意,您可以在C++中执行以上任何/所有操作。现在它不存在的原因是,大多数C++标准库都是围绕值语义而不是引用语义构建的。不管怎样,两者都是(国际海事组织)一种完全有效和合理的方法——有些语言采用其中一种,另一些则采用另一种。两者都可以很好地工作,但值语义恰好是在C++中做出的选择。

如果要复制指针,请创建指向map的指针的vector。你可以做到。

std::vector<std::map<A,B>* > x;

它不会自动做到这一点,因为它不知道你想让谁来管理内存。当vector超出范围时,是否应销毁map的对象。如果最初的map仍在范围内呢?