重载运算符 () 而不是 [] 进行索引

Sta*_*ine 4 c++ gcc operator-overloading visual-c++

()我正在重构的旧代码库有一种相当非正统的方法,通过重载运算符而不是运算符来访问 n 维向量[]

为了说明这一点,假设 Vec 是一个重载两个运算符的类,用于内部双精度列表的索引目的。

Vec v, w;
int index = 651;
double x = v(index);   // they index like this ..
double y = w[index];   // .. instead of like normally..
Run Code Online (Sandbox Code Playgroud)

我只能想到你这样做的一个充分理由:operator[]需要一个参数类型,size_t该类型可能取决于平台,也可能不uint64取决于平台。另一方面,代码中使用的索引类型主要是int,这意味着索引时需要进行大量隐式/显式类型转换。该代码的索引量非常大,所以我很犹豫是否要更改它。

这对于当今的现代编译器和 64 位平台真的有意义吗?我很快在https://godbolt.org/上进行了测试,您可以在这里尝试一下

我主要关注最新的 x64 gcc 和 Visual Studio 编译器,但在 x86-64 gcc (11.2) 中编译时会显示出差异。Gcccdqe()运算符添加了一条指令,我们知道这可能效率较低

我有点纳闷。为什么人们会做出这样的选择?

更新

正如答案中所解释的,我关于operator []被锁定到size_t字体大小的假设是不正确的。如果您使用索引int而不是uint64索引进行索引,则编译后的代码几乎相同,只是使用不同的寄存器和常量。

我必须说,为多个维度提供多个索引的想法()非常好。实际上并没有在代码库中的任何地方使用,所以我认为最好将其替换为[]. 我也很高兴看到它在 C++ 的未来版本中由正确的索引运算符处理。

Nat*_*ica 5

一个“问题”[]是当你有多个维度时。使用数组,您可以执行此操作arr[val1][val2],并且arr[val1]会给您一个可以用来索引的数组[val2]。对于类类型来说,这并不那么简单。没有[][]运算符,因此[val1]需要返回一个[val2]可以应用的对象。这意味着您需要创建另一种类型并提供您想要的所有功能。使用(),您可以做到这一点data(val1, val2),并且不需要任何中间对象。

  • 从 C++23 开始,“operator[]”可以采用多个下标。例如,声明为“T&operator[](std::size_t x, std::size_t y, std::size_t z);”的 3D 数组类的“operator[]”可以直接访问元素。请参阅[运算符重载,**数组下标运算符**](https://en.cppreference.com/w/cpp/language/operators)。 (4认同)
  • @BenVoigt 虽然这在技术上是一个重大变化,但我不知道它实际上会破坏哪些现实世界的代码。我不记得曾经在“[]”中看到过故意使用“,”。 (4认同)
  • 我们将来也许可以做“data[val1, val2]”。第一步,C++20 弃用 `[]` 内的逗号。 (2认同)
  • @Evg 不幸的是,选择了重大更改。可以通过元组或“std::initializer_list”支持多个索引。 (2认同)