访问数组元素的不同方式
Different ways to access array's element
据我所知,在 C++ 中有两种访问数组元素的方法:
int array[5]; //If we have an array of 5 integers
1) 使用方括号
array[i]
2) 使用指针
*(array+i)
我大学的老师强迫我使用*(array+i)
方法,告诉我"it's more optimized"。
所以,你能解释一下,它们之间有什么真正的区别吗?第二种方法比第一种方法有什么优势吗?
"My university's teacher forces me to use *(array+i)
method, telling me that "it's more optimized"."
请问他们在告诉你什么?如果您对这条语句 1 没有完全误解,请向他们索取有关生成的汇编代码的证明(此处为 @Christophe was giving one in )。当深入研究时,我不相信他们能给你这样的东西。
您可以使用例如-S
option GCC 生成汇编代码,并将获得的结果与一个或另一个版本进行比较。
任何体面的现代 C++ 编译器都会为这两个语句生成完全相同的汇编代码,只要它们引用任何 c++ fundamental types.
"Does the second method has any advantages over the first one?"
没有。相反的情况似乎发生了,因为代码的直观可读性较差。
1) 对于 class
/struct
类型,T& operator[](int index)
的重载可能在幕后进行,但如果是这样,*(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: 实现为数组的二维数学向量的距离。
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 等其他语言误导的人,在 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 会导致误导性的编译错误消息。
你必须知道你的对象的精确布局,你必须在每个公式中引入第一个维度的大小!
想象一下,稍后您想要增加二维数组中的元素数量。您必须重写所有内容!
语义差距
你的老师在这里遗漏的是运算符 []
的含义被编译器和 reader 很好理解。它是一种抽象,不依赖于您的数据结构在现实中是如何实现的。
假设你有一个数组和一个非常简单的代码:
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);
您的其余代码将起作用,因为 []
的语义对于两个数据结构是相同的。我让你想象如果你听从了你老师的建议会发生什么......
My university's teacher forces me to use *(array+i)
method, telling me that "it's more optimized".
你的老师完全错了。
标准将 array[i]
定义为等同于 *(array+i)
,编译器没有理由以其他方式对待它们。他们是一样的。两者都不会 "more optimized" 比另一个
推荐一个优于另一个的唯一原因是惯例和可读性,在这些比赛中,array[i]
获胜。
我想知道你的老师还错了什么? :(
据我所知,在 C++ 中有两种访问数组元素的方法:
int array[5]; //If we have an array of 5 integers
1) 使用方括号
array[i]
2) 使用指针
*(array+i)
我大学的老师强迫我使用*(array+i)
方法,告诉我"it's more optimized"。
所以,你能解释一下,它们之间有什么真正的区别吗?第二种方法比第一种方法有什么优势吗?
"My university's teacher forces me to use
*(array+i)
method, telling me that "it's more optimized"."
请问他们在告诉你什么?如果您对这条语句 1 没有完全误解,请向他们索取有关生成的汇编代码的证明(此处为 @Christophe was giving one in
您可以使用例如-S
option GCC 生成汇编代码,并将获得的结果与一个或另一个版本进行比较。
任何体面的现代 C++ 编译器都会为这两个语句生成完全相同的汇编代码,只要它们引用任何 c++ fundamental types.
"Does the second method has any advantages over the first one?"
没有。相反的情况似乎发生了,因为代码的直观可读性较差。
1) 对于 class
/struct
类型,T& operator[](int index)
的重载可能在幕后进行,但如果是这样,*(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: 实现为数组的二维数学向量的距离。
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 等其他语言误导的人,在 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 会导致误导性的编译错误消息。你必须知道你的对象的精确布局,你必须在每个公式中引入第一个维度的大小!
想象一下,稍后您想要增加二维数组中的元素数量。您必须重写所有内容!
语义差距
你的老师在这里遗漏的是运算符 []
的含义被编译器和 reader 很好理解。它是一种抽象,不依赖于您的数据结构在现实中是如何实现的。
假设你有一个数组和一个非常简单的代码:
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);
您的其余代码将起作用,因为 []
的语义对于两个数据结构是相同的。我让你想象如果你听从了你老师的建议会发生什么......
My university's teacher forces me to use
*(array+i)
method, telling me that "it's more optimized".
你的老师完全错了。
标准将 array[i]
定义为等同于 *(array+i)
,编译器没有理由以其他方式对待它们。他们是一样的。两者都不会 "more optimized" 比另一个
推荐一个优于另一个的唯一原因是惯例和可读性,在这些比赛中,array[i]
获胜。
我想知道你的老师还错了什么? :(