将许多载体累积到单个容器中,无需复制

时间:2013-09-13 07:02:38

标签: c++ c++11 containers move

在C ++ 11中是否可以累积许多std::vector,每个{1}返回给定一个函数(我的API无法更改)到std容器而不复制任何元素?

std::vector<int> make_vect();
container acc;                           // what is container?
do {
    acc.append(std::move(make_vect()));  // how to implement this?
} while(acc.size() < n);

注1 即使元素没有移动赋值运算符的移动构造函数,也不能复制元素,例如示例中的int。所以你可以移动一大块元素(通过复制指针),但不能移动单个元素。

注意2 container必须允许使用单个迭代器迭代所有累积元素。因此std::vector<std::vector<>>或类似内容允许。

显然,编写一个允许这个或使用std::list<std::vector<>>并提供自己的迭代器的容器是很简单的,但是std库是否提供了所需的功能而没有这些用户编写的添加内容?

似乎所要求的功能并不特别奇怪,我很惊讶即使使用C ++ 11也有多难(如果不是不可能的话)。

1 个答案:

答案 0 :(得分:3)

TL; DR 我认为标准容器库存不能满足您的要求。这就是原因。

请记住,容器的移动语义是有效的,因为它们被实现为动态分配内存的作用域绑定句柄。移动容器实现为复制句柄,而不触及包含的元素。

您的第一个(显式)约束不是复制任何容器的任何元素。这需要将句柄复制到您推定的acc_container中。换句话说,您需要acc_container<std::vector<T>>。无论单个T个元素有多大,任何标准容器都可以让您高效地完成这些任务。

您的第二个(隐式的,从注释中推断出来的)约束是您希望在所有单个向量的所有元素上具有统一的接口。换句话说,您希望将其用作acc_container<T>。这需要在acc_container的迭代器中有一个额外的间接层,迭代器检测到它已到达当前vector<T>之一的末尾,并跳转到下一个vector<T>的开头。 }。

标准库中不存在此类容器。

最简单的解决方法是使用std::vector<std::vector<T>>(以避免复制T元素),并编写自己的迭代器适配器(例如使用boost::indirect_iterator,以提供{{1}的迭代1}}元素)。

不幸的是,即使您提供non-member begin() / end()函数来初始化成员T / .begin()中的这些间接迭代器,range-for也不会使用ADL来查找这些函数,因为它会优先选择旧成员函数.end() / .begin()。此外,您将无法例如.end() insert()元素直接放入您的复合容器中,除非您还提供非成员T(并且类似于其他功能)。

因此,如果你想要一个真正的复合容器,具有范围支持和成员函数的本地接口,你需要自己编写一个(insert()作为后端,以及整个{{1在它上面写的接口)。也许你可以在Boost邮件列表上建议它作为一个很好的项目。

更新:这是Matt Austern在Segmented Iterators and Hierarchial Algorithms上发表的一篇旧论文的链接,该论文显示了这种方法带来的一些性能优势。缺点是你还需要让标准算法知道这些迭代器。

相关问题