简体   繁体   English

为什么会有花哨的指针?

[英]Why do fancy pointers exist?

I've always seen pointers as a specialization of iterators, used in the particular case where objects are stored contiguously in memory.我一直将指针视为迭代器的特化,用于对象连续存储在 memory 中的特殊情况。 However, I found out that the Allocator member type pointer (which then defines the same member type on iterators and containers) is not required to be a real pointer but it may be what's called a fancy pointer that, according to cppreference ,但是,我发现 Allocator 成员类型pointer (然后在迭代器和容器上定义相同的成员类型)不需要是真正的指针,但它可能是所谓的花哨指针,根据cppreference

is used to access objects allocated in address spaces that differ from the homogeneous virtual address space.用于访问分配在不同于同构虚拟地址空间的地址空间中的对象。

This is what I used to call an iterator but not a pointer, but that's not the point.这就是我以前所说的迭代器而不是指针,但这不是重点。 I'm wondering how an Allocator is not required to allocate contiguous memory.我想知道如何不需要分配器来分配连续的 memory。 Imagine passing a custom allocator to std::vector that does not allocate objects in a contiguous manner.想象一下,将自定义分配器传递给不以连续方式分配对象的std::vector For me that's not a vector anymore.对我来说,这不再是向量了。 If I don't want objects to be contiguous in memory I use a list rather than a vector with a custom allocator.如果我不希望对象在 memory 中是连续的,我使用列表而不是带有自定义分配器的向量。 They just look like a big source of confusion, why were they introduced?它们只是看起来很混乱,为什么要引入它们?

I've always seen pointers as a specialization of iterators我一直将指针视为迭代器的特化

Iteration of arrays is one of the uses of pointers. arrays的迭代是指针的用途之一。 It is not their only purpose.这不是他们唯一的目的。 They are also used as a "handle" to identify dynamic allocations.它们还用作识别动态分配的“句柄”。

why were [fancy pointers] introduced?为什么要引入[花式指针]?

The page that you linked explains a reason for their introduction:您链接的页面解释了他们介绍的原因:

Such pointers were introduced to support segmented memory architectures...引入此类指针以支持分段 memory 架构...

These days, such architectures are quite rare, but programmers have found other use cases:这些天来,这样的架构非常罕见,但程序员已经发现了其他用例:

... and are used today to access objects allocated in address spaces that differ from the homogeneous virtual address space that is accessed by raw pointers. ...并且今天用于访问分配在地址空间中的对象,这些地址空间与原始指针访问的同构虚拟地址空间不同。 An example of a fancy pointer is the mapping address-independent pointer boost::interprocess::offset_ptr , which makes it possible to allocate node-based data structures such as std::set in shared memory and memory mapped files mapped in different addresses in every process.花哨指针的一个例子是映射地址无关指针boost::interprocess::offset_ptr ,它可以分配基于节点的数据结构,例如共享 memory 和 memory 映射到不同地址的映射文件中的 std::set每一个过程。

The standard paper P0773R0 linked in the linked page has a more detailed list of purposes:链接页面中链接的标准论文P0773R0有更详细的用途列表:

  • Scenario A. "Offset" pointers with a modified bit-level representation.方案 A. 具有修改的位级表示的“偏移”指针。
  • Scenario B. Small-data-area "near" pointers.方案 B. 小数据区域“近”指针。
  • Scenario C.场景 C。 High-memory-area "far" pointers.高内存区域“远”指针。
  • Scenario D. "Fat" pointers carrying metadata for dereference-time.场景 D.“胖”指针携带用于取消引用时间的元数据。
  • Scenario E. "Segmented" pointers carrying metadata for deallocate-time.场景 E. “分段”指针携带用于解除分配时间的元数据。

Note that not all standard library implementations support all use cases of fancy pointers for all standard containers as explored in P0773R0.请注意,并非所有标准库实现都支持所有标准容器的花式指针的所有用例,如 P0773R0 中所述。

So, C++ as a language has a concept of a pointer.所以,C++作为一门语言有指针的概念。 For any type T* , the language requires certain specific things out of it.对于任何类型T* ,该语言都需要某些特定的东西。 In particular, sizeof(T*) is statically-determined, and all language pointers have the same size.特别是sizeof(T*)是静态确定的,并且所有语言指针都具有相同的大小。

In the long-before time however, the things that T* could work with did not reflect hardware capabilities.然而,在很久以前, T*可以使用的东西并没有反映硬件功能。 Imagine if hardware had two pools of memory, but these pools of memory have different maximum sizes.想象一下,如果硬件有两个 memory 池,但是这些 memory 池的最大大小不同。 So if the compiler mapped T* to the smaller pool, then one could not have a T* that points to the larger pool of memory.因此,如果编译器将T*映射到较小的池,则不能有一个T*指向较大的 memory 池。 After all, the address space of the larger memory would exceed the size of T* .毕竟,较大的 memory 的地址空间会超过T*的大小。

This led to the use of things like LONG_POINTER and the like for "pointing" into memory outside of the T* accessible space.这导致使用诸如LONG_POINTER之类的东西来“指向” T*可访问空间之外的 memory。

The goal of the allocator::pointer concept is to be able to write an allocator that can allow any allocator-aware container to work with such non- T* -compatible pools of memory transparently . allocator::pointer概念的目标是能够编写一个分配器,它可以允许任何分配器感知容器透明地与此类不兼容T*的 memory 池一起工作。

Of course... that is no longer relevant for most hardware.当然......这与大多数硬件不再相关。 Virtual memory, 32 and 64-bit addressing, and the like are now standard.虚拟 memory、32 位和 64 位寻址等现在是标准配置。 As such, if there's memory that's not directly accessible and you want to address it, the expectation is that you'll convert such memory into virtual addresses via OS calls which can then be used with language pointers just fine.因此,如果存在无法直接访问的 memory 并且您想要解决它,则期望您将通过操作系统调用此类 memory 转换为虚拟地址,然后可以很好地与语言指针一起使用。 See mapping of files and GPU memory.请参阅文件映射和 GPU memory。

It was intended to solve a problem at the library level, but the problem was instead solved at the hardware/OS level.它旨在解决库级别的问题,但问题却在硬件/操作系统级别解决。 Thus, it's an unnecessary complication of allocators and allocator-aware containers, but it remains present because of decisions made nearly 25 years ago.因此,这是分配器和分配器感知容器的不必要的复杂性,但由于近 25 年前做出的决定,它仍然存在。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM