处理指针时operator []的内部逻辑

时间:2017-08-18 21:48:20

标签: c++ arrays pointers

我几个月来一直在研究C ++,最近才决定更深入地研究指针和数组的逻辑。我在uni中教过的是非常基本的 - 指针包含变量的地址。创建数组时,基本上会创建指向其第一个元素的指针。

所以我开始尝试了一下。 (并得出了我需要确认的结论)。首先我创建了

int arr[10];
int* ptr = &arr[5];

正如你想象的那样

cout << ptr[3];

给了我数组的第8个元素。接下来我试了

int num = 6;
int* ptr2 = &num;
cout << ptr2[5];
cout << ptr2 + 5;

令我非常高兴(不讽刺)返回了相同的地址。即使num不是数组。

我得到的结论:数组在C ++中并不特别。它只是指向第一个元素的指针(已经输入)。更重要的是:我能否以class variable*的对象方式思考每个指针。 operator []中的class int*刚刚过载了吗?例如,要像以下那样:

int operator[] (int index){
    return *(arrayFirstaddress + index);
}

在这些实验中,我感兴趣的是operator []适用于每个指针。 (所以它就像为所述类的所有实例重载一个运算符一样)

当然,我可能会犯错误。我在网上找不到太多信息,因为我不知道怎么说出我的问题所以我决定在这里问一下。 如果你向我解释我是对还是错/非常错,为什么会非常有帮助。

2 个答案:

答案 0 :(得分:3)

您可以找到下标的定义,即c ++标准中的ptr2[5]这样的表达式,例如就像在this online c++ draft standard中一样:

  

5.2.1订阅[expr.sub]

     

(1)......表达式E1 [E2]与(定义)相同   *((E1)+(E2))

所以你的“发现”听起来是正确的,虽然你的例子似乎有一些错误(例如ptr2[5]不应该返回一个地址而是一个int值,而ptr2+5是一个地址而不是一个int值;我想你的意思是&ptr2[5])。

此外,您的代码不是此发现的证明,因为它基于未定义的行为。它可能产生支持你的“发现”的东西,但你的发现可能仍然无效,它也可能相反(真的!)。

它是未定义行为的原因是,如果结果超出分配的内存块ptr2+5指向的范围(即ptr2,则private void Entry_TextChanged(object sender, TextChangedEventArgs e) { Entry theEntry = (Entry)sender; string entryText = theEntry.Text; if(entryText != null && entryText.Length != 0) { char theMostRecentInput = entryText[entryText.Length - 1]; if(!Extension.IsNumeric(theMostRecentInput)) { theEntry.TextChanged -= Entry_TextChanged; theEntry.Text = e.OldTextValue; theEntry.TextChanged += Entry_TextChanged; } } } 和{{1}}是未定义的行为绝对是你的例子中的情况):

  

5.7添加运算符

     

(6)...除非两个指针都指向同一个数组的元素   对象,或者是数组对象的最后一个元素之后的行为   未定义。

不同的编译器,不同的优化设置,甚至程序中任何地方的微小修改都可以让编译器在这里做其他事情。

答案 1 :(得分:2)

C ++中的数组是对象的集合。指针是一个可以存储某些东西地址的变量。这两者不是一回事。

不幸的是,你的样本

int num = 6;
int* ptr2 = &num;
cout << ptr2[5];
cout << ptr2 + 5;

ptr2[5]ptr2 + 5的评估中表现出未定义的行为。指针表达式是特殊的 - 如果指针被操作(在这种情况下为ptr2)且结果(ptr2 + 5)在同一对象内,则涉及指针的算法仅具有已定义的行为。或者一个接一个结束(尽管解除引用“一个接一个结束”指针 - 试图访问它指向的值 - 也会给出未定义的行为)。

从语义上讲,*(ptr + n)ptr[n]是等价的(即它们具有相同的含义),如果ptr是指针且n是一个整数值。因此,如果评估ptr + n给出未定义的行为,那么评估ptr[n]也是如此。同样,&ptr[n]ptr + n也相同。

在表达式中,根据上下文,数组的名称​​转换为指针,该指针等于该数组的第一个元素的地址。所以,给定

  int x[5];
  int *p;
     // the following all have the same effect

  p = x + 2;
  p = &x[0] + 2;
  p = &x[2];

这并不意味着数组是指针。