gpt4 book ai didi

c++ - 将 std::uninitialized_fill() 与任何分配器一起使用是否有意义?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:41:06 24 4
gpt4 key购买 nike

std::uninitialized_fill()初始化内存有意义吗?当用户作为参数传递的分配器已用于获取内存本身时,在库中?我问这个是因为分配器应该提供自己的 construct()方法(allocate() 方法除外),其实现可能与标准方法不同,因此可能是 std::uninitialized_fill()并不总是适用于所有情况。

准确的说,我的疑惑来自Stroustrup写的C++书(附录E“Standard-Library Exception Safety”,E.3.1节),书中作者给出了一个template<class T, class A> vector<T,A>::vector(size_type n, const T& val, const A& a)的可能实现。 : 分配器 a 用于获取 vector 的内存,然后是 std::uninitialized_fill()用于初始化获取的内存。

他还给出了 std::uninitialized_fill() 的实现,它在内部使用标准放置 new 来初始化内存,但不再有 construct() 的证据。分配器的方法作为参数传递给 vector 构造函数。

最佳答案

我检查了 vector 的 GCC 实现,它是这样写的:

  vector(size_type __n, const value_type& __value,
const allocator_type& __a = allocator_type())
: _Base(__n, __a)
{ _M_fill_initialize(__n, __value); }

...

_M_fill_initialize(size_type __n, const value_type& __value)
{
this->_M_impl._M_finish =
std::__uninitialized_fill_n_a(this->_M_impl._M_start, __n, __value,
_M_get_Tp_allocator());
}

所以,看起来分配器的信息并没有消失。但是 uninitialized_fill_n_a 的代码很奇怪,它有两个重载(见下文),一个用于通用分配器,另一个用于 std::allocator .

通用调用,construct和特殊的 std::allocator只需调用 std::uninitialized_fill() .

所以,我的结论如下,

1) 所有 std::allocatorconstruct s 与 placement new 和

效果相同

2) 不能假设为通用分配器,或者至少 GCC std::vector不假设。 (根据@Michael Burr 的说法,您可以在 C++03 中假设这一点,不幸的是他没有提到 C++11)。

因此使用结构(即 std::allocator_traits<Alloc>::construct(alloc, pointer, value) )。

我个人的看法(在对此进行调查之后)是

我)std::uninitialized_fill有缺陷,因为分配器应该使用最后一个可选参数(或另一个重载),

ii) 作为解决方法,在您的实现细节中您应该有一个 .uninitialized_fill(first, last, value, alloc)完成工作的函数,包括异常处理(请注意下面的结构是如何展开的,并在失败时销毁)。

iii) 当前 std::unitialized_fill当你有关于分配器的信息时,它是非常无用的(基本上你必须重新实现它。)


现在是上面引用的代码:

  template<typename _ForwardIterator, typename _Size, typename _Tp,
typename _Allocator>
_ForwardIterator
__uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
const _Tp& __x, _Allocator& __alloc)
{
_ForwardIterator __cur = __first;
__try
{
typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
for (; __n > 0; --__n, ++__cur)
__traits::construct(__alloc, std::__addressof(*__cur), __x);
return __cur;
}
__catch(...)
{
std::_Destroy(__first, __cur, __alloc);
__throw_exception_again;
}
}

template<typename _ForwardIterator, typename _Size, typename _Tp,
typename _Tp2>
inline _ForwardIterator
__uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
const _Tp& __x, allocator<_Tp2>&)
{ return std::uninitialized_fill_n(__first, __n, __x); }

关于c++ - 将 std::uninitialized_fill() 与任何分配器一起使用是否有意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9755316/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com