gpt4 book ai didi

c++ - 具有自定义指针类型的内存分配器

转载 作者:IT老高 更新时间:2023-10-28 23:17:25 29 4
gpt4 key购买 nike

我尝试创建一个使用智能指针的自定义内存分配器。我没有发布代码,因为它太大并且没有添加太多信息。然后我用 std::vector 对其进行了测试.它在 Xcode 上运行良好。但是当我尝试在 Visual Studio 12 (2013) 中构建相同的代码时,构建失败并出现以下错误:

...vector(873): error C2660: 'std::_Wrap_alloc< my_allocator< int > >::construct' : function does not take 2 arguments

问题出在 push_back 方法中:

void push_back(value_type&& _Val)
{
....
this->_Getal().construct(this->_Mylast,
_STD forward<value_type>(this->_Myfirst[_Idx]));
....
}

错误信息有点困惑。真正的问题是 this->_Mylastmy_allocator< int >::pointer 类型,这是一个智能指针,构造方法需要 int* .

所以,问题很简单:自定义内存分配器中使用的指针类型有什么要求?应该 X::pointer可转换为原始指针?如果是,那它们就毫无用处了。

实际上我希望那行代码看起来像:

this->_Getal().construct(addressof(*(this->_Mylast)),
_STD forward<value_type>(this->_Myfirst[_Idx]));

让我们尝试在 C++ 标准中找到答案,它说:

[17.6.3.5-5] An allocator type X shall satisfy the requirements of CopyConstructible (17.6.3.1). The X::pointer, X::const_pointer, X::void_pointer, and X::const_void_pointer types shall satisfy the requirements of NullablePointer (17.6.3.3). No constructor, comparison operator, copy operation, move operation, or swap operation on these types shall exit via an exception. X::pointer and X::const_pointer shall also satisfy the requirements for a random access iterator (24.2)

如果我们看一下 NullablePointer reqs,它们会添加一些其他要求:

[17.6.3.3] A NullablePointer type is a pointer-like type that supports null values. A type P meets the requirements of NullablePointer if:
(1.1) — P satisfies the requirements of EqualityComparable, DefaultConstructible, CopyConstructible, CopyAssignable, and Destructible...

如果我检查随机访问迭代器要求,我也没有发现任何明确提及其转换为原始指针的内容。但在少数地方使用 addressof 的方法使用(例如 24.2.1-5)。

此外,它不是 Microsoft 的 std::vector 中唯一的地方。实现地点X::pointer和原始指针被假定为相等。我想知道,我错过了什么?

编辑:我将在此处添加一段 my_allocator 定义:

class my_allocator
{
public:

typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef my_ptr<T> pointer;
typedef my_ptr<const T> const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
typedef my_ptr<void> void_pointer;
typedef my_ptr<const void> const_void_pointer;

<constructors>

pointer allocate(size_type n, const_void_pointer = nullptr);
void deallocate(const pointer& ptr, size_type elements_num);
};

最佳答案

为了解决这个问题,我创建了一个 to_raw_pointer 函数,它恰好适用于任何实现 operator->() 的“花式指针”。您可以在 libc++ implementation 中找到它.

这里是:

template <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
_Tp*
__to_raw_pointer(_Tp* __p) _NOEXCEPT
{
return __p;
}

template <class _Pointer>
inline _LIBCPP_INLINE_VISIBILITY
typename pointer_traits<_Pointer>::element_type*
__to_raw_pointer(_Pointer __p) _NOEXCEPT
{
return _VSTD::__to_raw_pointer(__p.operator->());
}

它通过以非常规方式调用 operator->() 来工作。这个操作符必须要么调用另一个operator->(),要么返回一个真正的指针。实指针的重载用恒等函数打破了递归。所以这会像这样使用:

this->_Getal().construct(__to_raw_pointer(this->_Mylast),
_STD forward<value_type>(this->_Myfirst[_Idx]));

construct 被指定为采用真正的指针,而不是花哨的指针。并且没有指定从花哨指针到实际指针的隐式转换。容器必须使用诸如 to_raw_pointeraddressof 之类的东西。

容器还需要通过 allocator_traits 调用 construct,而不是如图所示直接在存储的分配器上调用它。这是为了允许 constructallocator_traits “默认”,而不是要求分配器实现 construct

目前,operator*()operator->() 通常都要求花哨的指针在调用该运算符之前非空。但是我预计将来 operator->() 的这一要求会放宽。

更新

我写上面的时候有点着急。现在我有时间了,我将包含对 allocator::pointer 类型的完整要求。然而,在重新阅读问题时,我看到 Maxym题主已经做好了,这里不再赘述。

在std中但并不完全明显的一件事是四种指针类型之间的隐式和显式转换:pointerconst_pointervoid_pointerconst_void_pointer:

implicit allocator pointer conversions:
+--------------------------------------+
| pointer --> const_pointer |
| | \ | |
| | --------- | |
| \|/ _\| \|/ |
| void_pointer --> const_void_pointer |
+--------------------------------------+


explicit allocator pointer conversions:
+--------------------------------------+
| pointer const_pointer |
| /|\ /|\ |
| | | |
| | | |
| void_pointer const_void_pointer |
+--------------------------------------+

也就是说,你可以从非const隐式转换为const,从非void隐式转换为void,您可以显式void 转换为非void。但是容器无法从 allocator::const_pointerallocator 中const_cast(抛弃const-ness): :const_void_pointer。一旦容器进入const,就再也回不来了。

关于c++ - 具有自定义指针类型的内存分配器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27646996/

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