gpt4 book ai didi

用于负数组索引的 C++ size_t 和 ptrdiff_t

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

我很难在 size_t 之间做出选择和 ptrdiff_t对于索引的类型,应该需要能够存储负值。

准确地说,在我的代码中我需要实现一个数组。我收到它的长度(在构造函数中)作为 size_t 的类型,当我重载 [] operator我需要索引的类型为 ptrdiff_t (而不是 size_t ),因为我想允许负索引,如本例所示:

std::size_t length = 50;
MyVector<int> vec(length);
vec[0] = 10;

MyVector<int> vec2 = vec+1;
std::cout << vec2[-1] << std::endl; //should print 10

上述设计引起的问题是可用索引的范围受限于 ptrdiff_t 的最大值。 , 在某些机器上,这个上限小于 size_t 的最大值

std::numeric_limits<std::ptrdiff_t>::max() < std::numeric_limits<std::size_t>::max()

因此,问题是用户可能会创建一个大小大于 ptrdiff_t 的最大值的数组。 (但仍在 size_t 的范围内,当然),但他将无法访问成功超过 ptrdiff_t 最大值的数组元素。 ,因为它们的索引会溢出到负数。在我的机器上,这会将可用索引减半! (因为size_tptrdiff_t都是64位的,但是一个是unsigned,另一个是signed)

以下是我想出的解决方案,但遗憾的是它们都不是完美的:

  1. 在构造函数中,接受 ptrdiff_t 类型的长度而不是 size_t , 并添加一个检查来验证给定的长度不是负数。

    优点:它解决了这个问题,因为现在我将无法访问数组中的所有元素,并且仍然允许负索引。

    缺点:它限制了数组的最大可能长度。 (例如,就像我之前说的,在我的机器中它减少了一半)

  2. 保持原样,但在 [] operator 中, 将索引转换为类型 size_t ,并利用负值会溢出的事实。

    即对于给定的索引,添加我们当前指向的元素与

    之间的差异

    例如,在我之前的示例中,由于 vec2 指向数组中的 second 元素,因此 [] operator看起来像

    template<class T>
    T& MyVector<T>::operator[] (std::ptrdiff_t index) {
    //Since vec2 points to the second element, we add 1.
    //For vec, we would add 0 since it points at the
    //first element in the array.
    std::size_t actual_index = static_cast<std::size_t>(index + 1);

    //Do boundary checking

    return this->ptr[actual_index];
    }

    优点:我们现在能够访问数组中的所有元素。

    缺点: 用法变得笨拙和丑陋。例如,如果我们创建一个大小为 std::numeric_limits<std::size_t>::max() 的 vector , 那么为了访问最后一个元素,我们需要访问 '-1' 元素:

    MyVector<int> big_vector(std::numeric_limits<std::size_t>::max());
    big_vector[-1] = 5; // big_vector[-1] is the last element in the array.

    MyVector<int> big_vector2 = big_vector + 1;
    std::cout << big_vector2[-2] << std::endl; // would print 5, since big_vector2 points at the second element in the array

最佳答案

I'm having difficulty choosing between size_t and ptrdiff_t for the type of an index, which should need to be able to store a negative value.

为什么您将自己限制为 size_t 和 ptrdiff_t?其他整数类型呢?

您是否有实现包含 4.294.967.296 个元素的容器的实际计划? (即 2 ^ 32)。

我不认为现在有一个平台可以分配那么多内存——至少在消费级计算机中是这样。您正在研究专用硬件吗?

对于通用 C++,您可以安全地编写 std::size_t - 接受 std::ptrdiff_t 索引类的构造函数。

您可能必须配置接受的索引范围,这样如果您接受负索引,有效索引范围应该是 (-max32bit, max32bit)。

这意味着,如果您尝试使用索引在 (max32bit, max64bit) 范围内的类,您的类应该抛出异常。

我的解决方案将在构造函数中接受 std::size_t(有明确的文档说明索引范围从 -max(ptrdiff_t) 到 max( ptrdiff_t),而不是从 0 到 max(std::size_t)。然后将使用 std::ptrdiff_t 对该类进行索引。

关于用于负数组索引的 C++ size_t 和 ptrdiff_t,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31914987/

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