访问数组元素的不同方法

时间:2015-03-23 19:57:59

标签: c++ arrays pointers element

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

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

1)使用方括号

array[i]

2)使用指针

*(array+i)

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

那么,请你解释一下,它们之间有什么真正的区别吗?第二种方法是否比第一种方法有任何优势?

3 个答案:

答案 0 :(得分:11)

一个选项是否比另一个更优化?

好吧,让我们看一下用MSVC2013生成的汇编代码(NON-OPTIMIZED调试模式):

; 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上写道:过早优化是所有邪恶的根源。你的老师应该知道!

有一个优势吗?

显然,选项一具有直观和可读的优点。 Option2在数学应用程序中变得很快无法实现。

示例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等其他语言误导的人,**意味着“权力”

示例2:计算2x2矩阵的determinant

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);

对于多维数组,选项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); 

其余代码将起作用,因为[]的语义对于两个数据结构是相同的。我让你想象一下,如果你已经使用了老师的建议,会发生什么事情......

答案 1 :(得分:9)

  

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

他们告诉你什么?如果你没有对这个语句 1 没有完全错误,请向他们询问有关生成的汇编代码的证明(@Christophehis answer中给出了一个)。当我深入研究时,我不相信他们会给你这样的。

您可以使用以下方法轻松自行检查。 GCC的-S option生成汇编代码,并将获得的结果与一个或另一个版本进行比较。

任何体面的,现代的C ++编译器都会为这两个语句生成完全相同的汇编代码,只要它们引用任何c++ fundamental types

  

“第二种方法是否比第一种方法有任何优势?”

没有。由于代码的可读性不太直观,似乎会出现相反的情况。


1)对于class / struct类型,T& operator[](int index)可能会出现在幕后执行操作的重载,但如果是这样,*(array+i)应该是实施以保持一致。

答案 2 :(得分:7)

  

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

您的老师绝对错误

标准定义array[i]等同于*(array+i),编译器没有理由对其进行处理。他们是一样的。两者都不会更优化&#34;比另一个。

推荐一个优于另一个的唯一理由是约定和可读性,在那些比赛中,array[i]获胜。

我想知道你的老师还有什么问题? :(