【问题标题】:Correct types for matrix size and looping variables矩阵大小和循环变量的正确类型
【发布时间】:2020-12-25 06:56:20
【问题描述】:

在下面的示例中,我是否为大小和循环索引选择了正确的类型。似乎有很多选择,int 似乎出现在大多数临时示例中。什么是我的简单示例使用的规范/最佳实践/正确类型。我选择了size_t,因为它代表行/列矩阵大小,ptrdiff_t 代表索引,因为它涉及指针运算。

template<size_t N, size_t P, size_t M>
void naive_multiply(T* A, T* B, T* C) {
    for(ptrdiff_t i=0; i!=N; ++i) {
        for(ptrdiff_t j=0; j!=M; ++j) {
            for(ptrdiff_t k=0; k!=P; ++k) {
                C[i + j*M] += A[i + k*P] * B[k + j*M];
            }
        }
    }
};

我对上述内容的唯一保留是隐式类型转换,但是,我可能不知道它们是彼此的别名(如果它们是的话)。我还考虑将uint_ptr_t 用作循环索引。

【问题讨论】:

  • 您的容器可能有一个用于“size_type”和“difference_type”的 typedef,或者如果您只是使用原始数组,这会引发一些运行时与编译时的问题,但您当前的选择似乎是合理的对于那些类型。 (基于意见)
  • 您的索引不涉及指针运算。在提供的示例代码中,除了索引本身之外,您绝不会对指针进行算术运算。而且您当然没有进行需要支持有符号值的指针算术。有关详细信息,请参阅我的答案。

标签: c++ for-loop types


【解决方案1】:

免责声明:这些是意见,但主要是出于所提及类型的意图。

size_t 似乎是表示数组中元素数量的正确类型。毕竟,size_t 被定义为足够大以容纳任何对象的大小,包括任何数组。事实上,sizeof() 的返回类型始终是size_t

使用ptrdiff_t 进行索引有点欺骗性,除非您想支持负索引(或者如果您正在向后迭代数组并且您希望负索引作为停止标准;请参阅here) ,因为它是有符号类型。这就是为什么它被称为ptrdiff_t;它最初旨在表示两个附近指针之间的差异(可以是负数)。在您的示例中,您的任何索引变量都不应该是负数。大小也永远不会是负数。您的算术只涉及计算非负值的总和和乘积,因此算术输出也永远不会是负数。因此,没有理由使用像ptrdiff_t 这样的有符号类型。 size_t 在这里也足够了;如果它可以表示数组中的元素个数,也可以表示数组中的任何有效索引。

您可能不想将uintptr_t 用于循环索引。 uintptr_t 设计用于当您希望将指针视为整数以执行类似整数的操作时。例如,您可能(出于某种奇怪的原因)想要对指针进行按位算术,或者您可能(出于某种奇怪的原因)想要故意不对齐它。像这样的情况是不寻常的;可能更常见的是使用uintptr_t 来掩盖它完全是一个指针的事实,以便它可以更像一个“句柄”来对待(例如,暗示应用程序不应该尝试取消引用或删除它)。您的索引根本没有被视为指针(它们只是被视为乘以大小的索引);它们当然不会被视为需要对其进行类似整数运算的指针。

结论:除非您出于某种原因想要支持负索引,否则只需对大小和索引变量都使用size_t

【讨论】:

  • 这是一个很好的答案。一个问题是,size_t 是否适合索引,因为索引在技术上不是某物的大小而是位置?
  • Cory Nelson 在这里给出了一个很好的答案:stackoverflow.com/questions/55604029/…
猜你喜欢
  • 2021-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多