Um ponteiro não const para um elemento do array pode ser usado para acessar o array inteiro, o que exigiria que o compilador recarregasse quaisquer elementos do array buscados anteriormente na memória:
void use_value(int* a) {
a[1] = 2; // change array pointed to by a
}
void do_thing() {
int a[] = {1, 2, 3};
calculate(a[1]); // do something with this value (presumably a[1] will be stored in a register)
use_value(&a[0]);
calculate(a[1]); // the compiler must now reload a[1] from memory
}
O que estou pensando é se esse problema ocorre se o ponteiro for alterado para uma referência:
void use_value(int& a) {
(&a)[1] = 2; // is this UB?
}
void do_thing() {
int a[] = {1, 2, 3};
calculate(a[1]); // do something with this value (presumably a[1] will be stored in a register)
use_value(a[0]);
calculate(a[1]); // must the compiler now reload a[1] from memory?
}
Vincular uma referência a um objeto e então usá-la para obter um ponteiro para esse objeto produz o mesmo valor de ponteiro que fazer isso sem a referência, então a aritmética definitivamente se aplica. Todos os elementos de um array (mas não o array em si) formam um alias juntos como resultado.
O padrão não define nada para que isso aconteça (é apenas outro ponteiro para o objeto), mas reconhece essa situação (ao limitar o poder de
std::launder
) ao definir quando um byte de memória pode ser alcançado por meio de um valor de ponteiro ([basic.compound]/6).