访问数组元素的不同方式

Different ways to access array's element

本文关键字:方式 数组元素 访问      更新时间:2023-10-16

据我所知,在C++中有两种访问数组元素的方法:

int array[5]; //If we have an array of 5 integers

1)使用方括号

array[i]

2)使用指针

*(array+i)

我所在大学的老师强迫我使用*(array+i)方法,告诉我"它更优化了"。

那么,你能解释一下,它们之间有什么真正的区别吗?第二种方法比第一种方法有什么优点吗?

一个选项比另一个选项更优化吗

好吧,让我们看看在实践中使用MSVC2013(非优化调试模式)生成的汇编程序代码:

; 21   :    array[i] = 8; 
    mov eax, DWORD PTR _i$[ebp]
    mov DWORD PTR _array$[ebp+eax*4], 8
; 22   :    *(array + i) = 8; 
    mov eax, DWORD PTR _i$[ebp]
    mov DWORD PTR _array$[ebp+eax*4], 8

好吧,恕我直言,我看不出生成的代码有什么不同。

顺便说一句,最近有人在SO上写道:过早优化是万恶之源。你的老师应该知道!

一个比另一个有优势吗

显然,选项一具有直观易读的优点。选项2在数学应用程序中很快变得不可读。

示例1:实现为数组的2D数学向量的距离。

double v[2] = { 2.0, 1.0 };
// option 1:  
double d1 = sqrt(v[0] * v[0] + v[1] * v[1]);
//option 2: 
double d2 = sqrt(*v**v + *(v + 1)**(v + 1));

事实上,由于**,第二个选项确实具有误导性,因为你必须仔细阅读公式才能理解它是双重解引用还是与解引用指针相乘。不说那些可能被一些其他语言误导的人,比如ADA,其中CCD_;功率";

示例2:计算2x2矩阵的行列式

double m[2][2] = { { 1.0, 2.0 }, { 3.0, 4.0 } };
// option 1
double dt1 = m[0][0] * m[1][1] - m[1][0] * m[0][1]; 
// option 2
double *x = reinterpret_cast<double*>(m); 
double dt2 = *x **(x+2*1+1) - *(x+2*1) * *(x+1);

对于多维arays,选项2是一场噩梦。注意:

  • 我使用了一个临时的一维指针x来使用这个公式。在这里使用m会导致误导性的编译错误消息。

  • 你必须知道你的对象的精确布局,你必须在每个公式中引入第一个维度的大小!

想象一下,稍后您想要增加2D阵列中的元素数量。你必须重写所有内容!

语义差距

您的老师在这里缺少的是,运算符[]具有编译器和读者都能很好理解的含义。它是一种抽象,不依赖于您的数据结构在现实中是如何实现的。

假设您有一个数组和一个非常简单的代码:

int w[10] {0}; 
... // put something in w
int sum = 0; 
for (int i = 0; i < 10; i++)
    sum += w[i];  

后来您决定使用std::vector而不是数组,因为您已经了解到它更加灵活和强大。您所要做的就是更改w:的定义(和初始化)

vector<int> w(10,0); 

代码的其余部分将起作用,因为[]的语义对于这两种数据结构是相同的。我让你想象一下,如果你听从老师的建议会发生什么。。。

"我大学的老师强迫我使用*(array+i)方法,告诉我"它更优化了"。"

他们在告诉你什么?如果您对1这句话没有完全错误,请向他们询问有关生成的汇编代码的证明(@Christophe在这里的回答中给出了一个)。我不相信他们会给你这样的,当深入观察时。

您可以使用GCC的-S选项来生成汇编代码,并将所获得的结果与一个或另一个版本进行比较,从而轻松地自己检查这一点。

任何像样的现代C++编译器都会为这两条语句生成完全相同的汇编代码,只要它们引用任何C++基本类型。

"第二种方法比第一种方法有什么优势吗?"

没有。相反的情况似乎发生了,因为代码的直观可读性较差。


1)对于class/struct类型,可能存在在幕后执行任务的T& operator[](int index)的过载,但如果是这样,则应实现*(array+i)以使其行为一致。

我所在大学的老师强迫我使用*(array+i)方法,告诉我"它更优化了"。

你的老师完全错了

该标准将array[i]定义为等效于*(array+i),编译器没有理由以其他方式对待它们。他们是一样的。两者都不会比另一个"更优化"。

推荐一个胜过另一个的唯一原因是惯例和可读性,在这些比赛中,array[i]获胜。

我想知道你的老师还做错了什么(