Eu tenho uma matriz C++:
std::array<int, 10> arr { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Quero reverter os últimos cinco elementos, para terminar com { 0, 1, 2, 3, 4, 9, 8, 7, 6, 5 }
. Eu sei std::array
que me dá iteradores de acesso aleatório, então posso definitivamente escrever isto:
std::reverse(arr.begin() + 5, arr.end());
Mas, me pergunto sobre algumas outras abordagens possíveis.
T*
é um iterador de acesso aleatório, então eu poderia escrever isto:
std::reverse(&arr[5], &arr[arr.size()]);
O que tenho quase certeza de que está bem definido, já que é permitido fazer referência (mas não acessar) um após o final de um array.
O que estou querendo saber é se isso é permitido:
std::reverse(&arr[5], arr.end());
Isso é executado na minha máquina, mas isso não significa que seja um comportamento padrão.
Se arr
fosse um array estilo C T[]
, então seu tipo de iterador é obviamente T*
. Mas, pelo menos à primeira vista, não vejo nenhuma garantia que std::array<T, C>::iterator
seja igual T*
ou mesmo comparável a ela.
O padrão garante que a linha de código acima funcione? É std::array<T, C>::iterator
garantido que s sejam compatíveis com ponteiros para T
elementos da matriz?
Não,
std::array<T, C>::iterator
não é garantido que seja umT*
ponteiro bruto ou comparável a umT*
ponteiro bruto. Nada impede que uma implementação use um tipo de proxy paraiterator
(para fornecer depuração, verificação de limites, etc.), assim como qualquer outro tipo de contêiner.Além disso,
arr[arr.size()]
é um comportamento indefinido , pois acessa um elemento que está fora dos limites, assim&arr[arr.size()]
como um comportamento indefinido , pois você está obtendo o endereço de um elemento que não existe. Mas usararr.begin()+arr.size()
e&arr[0]+arr.size()
ambos são seguros para criar um iterador/ponteiro completo (desde que você não os desreferencia).