考虑以下程序,它将一系列元素插入到向量中:
vector<string> v1;
vector<string> v2;
v1.push_back("one");
v1.push_back("two");
v1.push_back("three");
v2.push_back("four");
v2.push_back("five");
v2.push_back("six");
v1.insert(v1.end(), v2.begin(), v2.end());
这样可以有效地复制范围,在目标向量中为整个范围分配足够的空间,以便最多需要一次调整大小。 现在考虑以下程序,它尝试将范围移动到向量中:
vector<string> v1;
vector<string> v2;
v1.push_back("one");
v1.push_back("two");
v1.push_back("three");
v2.push_back("four");
v2.push_back("five");
v2.push_back("six");
for_each ( v2.begin(), v2.end(), [&v1]( string & s )
{
v1.emplace_back(std::move(s));
});
这将执行成功的移动,但不能享受 insert() 在目标向量中预分配空间的好处,因此在操作过程中可以多次调整向量的大小。
所以我的问题是,是否有可以将范围移动到向量中的插入等效项?
您使用带有insert
的move_iterator
:
v1.insert(v1.end(), make_move_iterator(v2.begin()), make_move_iterator(v2.end()));
24.5.3 中的示例几乎正是这个。
如果 (a) vector::insert
使用迭代器标记调度来检测随机访问迭代器并预先计算大小(您在复制的示例中假设它确实如此),并且 (b) move_iterator
保留它包装的迭代器的迭代器类别(这是标准所要求的)。
在一个晦涩的点上:我很确定vector::insert
可以从源进行放置(这在这里无关紧要,因为源与目标的类型相同,因此放置与复制/移动相同,但与其他相同的示例相关)。我还没有找到需要这样做的声明,我只是从迭代器对的要求i,j
传递给insert
的事实中推断出T
从*i
EmplaceConstructible
。
-
std::move
预分配算法:#include <iterator> #include <algorithm> v1.reserve(v1.size() + v2.size()); // optional std::move(v2.begin(), v2.end(), std::back_inserter(v1));
-
以下内容将更加灵活:
v1.insert(v1.end(), std::make_move_iterator(v2.begin()), std::make_move_iterator(v2.end()));
史蒂夫·杰索普(Steve Jessop)提供了有关其确切功能以及可能如何这样做的背景信息。