访问数组元素的不同方法

E_T*_*ony 6 c++ arrays pointers element

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

int array[5]; //If we have an array of 5 integers
Run Code Online (Sandbox Code Playgroud)

1)使用方括号

array[i]

2)使用指针

*(array+i)
Run Code Online (Sandbox Code Playgroud)

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

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

Chr*_*phe 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
Run Code Online (Sandbox Code Playgroud)

好吧,有了最好的意愿,我看不出生成的代码有什么不同.

顺便提一下,有人最近在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));
Run Code Online (Sandbox Code Playgroud)

事实上,第二个选项实际上是误导的**,因为你必须仔细阅读公式,以了解它是否是一个双重引用或乘以一个解除引用的指针.不是说那些可能被ADA等其他语言误导的人,**意思是"权力"

实施例2:所述的计算行列式的2×2矩阵的

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);
Run Code Online (Sandbox Code Playgroud)

对于多维数组,选项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];  
Run Code Online (Sandbox Code Playgroud)

之后你决定使用a std::vector而不是数组,因为你已经知道它更加灵活和强大.您所要做的就是更改以下内容的定义(和初始化)w:

vector<int> w(10,0); 
Run Code Online (Sandbox Code Playgroud)

其余代码将起作用,因为[]两个数据结构的语义相同.我让你想象一下,如果你使用过老师的建议会有什么问题......


πάν*_*ῥεῖ 9

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

他们告诉你什么?如果你没有对这个陈述1完全错误,请向他们询问有关生成的汇编代码的证明(@Christophe在这里给出了答案).当我深入研究时,我不相信他们会给你这样的.

您可以使用例如GCC -S选项生成汇编程序代码,并将结果与​​一个或另一个版本进行比较,从而轻松地自行检查.

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

"第二种方法比第一种方法有任何优势吗?"

不会出现相反情况,因为代码的可读性不太直观.


1)对于class/ struct类型,可能会有T& operator[](int index)幕后做事的重载,但如果是这样,*(array+i)应该实现一致的行为.


Lig*_*ica 7

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

你的老师是完全错的.

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

推荐一个而不是另一个的唯一原因是约定和可读性,并且在那些比赛中array[i]获胜.

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