我想知道事情是如何工作的,因此一直在深入研究 c++ 标准库。前几天我发生了什么事。
要求容器(例如:)std::vector<int, std::allocator<int> >
使用为分配指定的分配器。具体来说,标准说:
23.1.8
此子句中定义的所有容器类型的复制构造函数从它们各自的第一个参数中复制分配器参数。这些容器类型的所有其他构造函数都采用 Allocator& 参数 (20.1.5),这是一个值类型与容器的值类型相同的分配器。此参数的副本用于在每个容器对象的生命周期内由这些构造函数和所有成员函数执行的任何内存分配。在此子句中定义的所有容器类型中,成员 get_allocator() 返回用于构造容器的分配器对象的副本。
同样在标准的后面它说(在几个不同的地方,但我会选择一个)这样的事情:
explicit deque(size_type n, const T& value = T(), const Allocator& = Allocator());
效果:使用指定的分配器构造具有 n 个值副本的双端队列。
好的,继续我的问题。
让我们std::vector
以实现以下内容的自然而有效的方式为例:
vector<T, A>::vector(const vector& x)
可能看起来像这样:
template <class T, class A>
vector<T, A>::vector(const vector& x) {
pointer p = alloc_.allocate(x.size());
std::uninitialized_copy(x.begin(), x.end(), p);
first_ = p;
last_ = p + x.size();
end_ = p + x.size();
}
具体来说,我们分配一些内存,然后将所有成员复制到适当的位置。不必费心做类似的事情,new value_type[x.size()]
因为那会默认构造数组只是为了覆盖它!。
但是,这不使用分配器来进行复制构造......
我可以手动编写一个循环来执行以下操作:
while(first != last) {
alloc_.construct(&*dest++, *first++);
}
但这是一种浪费,它几乎与 相同std::uninitialized_copy
,唯一的区别是使用分配器而不是放置新的。
那么,您是否认为标准没有(对我来说似乎很明显)这样的一组功能是一种疏忽:
template <class In, class For, class A>
For uninitialized_copy(In first, In last, For dest, A &a);
template <class In, class Size, class For, class A>
For uninitialized_copy_n(In first, Size count, For dest, A &a);
template <class For, class T, class A>
void uninitialized_fill(For first, For last, const T& x, A &a);
template <class For, class Size, class T, class A>
void uninitialized_fill_n(For first, Size count, const T& x, A &a);
我想,如果人们想在那里实现自己的容器等并有效地利用复制构造,那么这些类型的函数(即使手动实现它们是微不足道的......直到你试图让它们异常安全)将被证明是相当有用的在使用分配器时。
想法?