简体   繁体   English

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

[英]C++ size_t and ptrdiff_t for negative array indexing

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_tptrdiff_t之间选择索引类型,它应该能够存储负值。

To be precise, in my code I need to implement an array. 确切地说,在我的代码中,我需要实现一个数组。 I receive it's length (in the constructor) as a type of size_t , and when I overloaded the [] operator I need that the index would be of type ptrdiff_t (and not size_t ), since I want to allow negative indexes, as this example shows: 我接收它的长度(在构造函数中)作为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

The issue that arises from said design is that the range of avaiable indexes is limited by the maximum value of ptrdiff_t , and in some machines, this upper limit is less than the maximum value of size_t . 所述设计产生的问题是可用索引的范围受到ptrdiff_t的最大值的限制,并且在一些机器中, 该上限小于size_t的最大值

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

Thus, the problem is that the user might create an array with a size which is larger than the maximum value of ptrdiff_t (but still in range of size_t , of course), but he wouldn't be able to access the array's elements which succeed over the maximum value of ptrdiff_t , because their indexes would overflow to a negative number. 因此,问题是用户可能会创建一个大小大于ptrdiff_t最大值的数组(当然,仍然在size_t范围内), 但是他无法访问成功的数组元素超过ptrdiff_t的最大值 ,因为它们的索引会溢出到负数。 On my machine, this cuts the avaiable indexes in half! 在我的机器上,这将可用的索引减少了一半! (since both size_t and ptrdiff_t are 64 bits, but one is unsigned and the other is signed ) (因为size_tptrdiff_t都是64位,但是一个是unsigned ,另一个是有signed

Here are the solutions that I came up with, but sadly none of them are perfect: 以下是我提出的解决方案,但遗憾的是它们都不是完美的:

  1. In the constructor, accept a length of type ptrdiff_t instead of size_t , and add a check that verifies that the given length is not negative. 在构造函数中,接受类型为ptrdiff_t而不是size_t的长度,并添加一个检查以验证给定长度不是负数。

    Pros: It solves the issue, since now I would be able ot access all the elements in the array, and still allow for negative indexes. 优点:它解决了这个问题,因为现在我可以访问数组中的所有元素,并且仍然允许负索引。

    Cons: It limits the maximum possible length of the array. 缺点:它限制了数组的最大可能长度。 (eg like I said earlier, in my machine it cuts by half) (就像我之前说过的那样,在我的机器中减少了一半)

  2. Leave things as they are, but in the [] operator , cast the index to type size_t , and make use of the fact that negative value would overflow. 保持原样,但在[] operator ,将索引转换为size_t类型,并利用负值溢出的事实。

    ie to the given index, add the difference between the element we're currently pointing to, and the 即对于给定的索引,添加我们当前指向的元素与之间的差异

    for example, in my example before, since vec2 points to the second element in the arary, the [] operator would look something like 例如,在我之前的例子中,由于vec2指向arary中的第二个元素, [] 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]; } 

    Pros: We're now able to access all the elements in the array. 优点:我们现在能够访问数组中的所有元素。

    Cons: The usage becomes clumsy and ugly. 缺点:使用变得笨拙和丑陋。 For example, if we create a vector of size std::numeric_limits<std::size_t>::max() , then in order to access the last element, we need to access the '-1' element: 例如,如果我们创建一个大小为std::numeric_limits<std::size_t>::max()的向量,那么为了访问最后一个元素,我们需要访问'-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之间选择索引类型,它应该能够存储负值。

Why have you limited yourself to size_t and ptrdiff_t? 你为什么限制自己的size_t和ptrdiff_t? What about other integer types? 其他整数类型怎么样?

Do you have an actual plan to implement a container with 4.294.967.296 elements? 您是否有实际计划来实现具有4.294.967.296元素的容器? (that is 2 ^ 32 ). (即2 ^ 32 )。

I don't think there is a platform today that will assign that much memory - at least, not in consumer-level computers. 我不认为今天有一个平台可以分配那么多的内存 - 至少,不是在消费级计算机上。 Are you working on specialized hardware? 你在使用专门的硬件吗?

For generic-purpose C++, you can safely write a std::size_t - accepting constructor to a std::ptrdiff_t indexed class. 对于通用C ++,您可以安全地将std::size_t - 接受构造函数写入std::ptrdiff_t索引类。

You will probably have to configure the accepted range of indexes, so that if you accept negative indexes, effective index range should be (-max32bit, max32bit). 您可能必须配置可接受的索引范围,因此如果您接受负索引,则有效索引范围应为(-max32bit,max32bit)。

This means, if you attempt to use the class with an index in the range (max32bit, max64bit), your class should throw an exception. 这意味着,如果您尝试使用范围内的索引(max32bit,max64bit)的类,则您的类应该抛出异常。

My solution would accept a std::size_t in the constructor (with clear documentation stating that the index ranges from -max( ptrdiff_t ) to max( ptrdiff_t ), and not from 0 to max( std::size_t ). The class would then be indexed using a std::ptrdiff_t . 我的解决方案将在构造函数中接受std::size_t (有明确的文档说明索引范围从-max( ptrdiff_t )到max( ptrdiff_t ),而不是从0到max( std::size_t )。使用std::ptrdiff_t索引。

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

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