Considere el siguiente código:cuerdas s; &s+1; Legal? UB?
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
string myAry[] =
{
"Mary",
"had",
"a",
"Little",
"Lamb"
};
const size_t numStrs = sizeof(myStr)/sizeof(myAry[0]);
vector<string> myVec(&myAry[0], &myAry[numStrs]);
copy(myVec.begin(), myVec.end(), ostream_iterator<string>(cout, " "));
return 0;
}
Resulta de interés &myAry[numStrs]
: numStrs es igual a 5, por lo que &myAry[numStrs]
apunta a algo que no existe; el sexto elemento en la matriz. Hay otro ejemplo de esto en el código anterior: myVec.end()
, que apunta a un extremo del vector myVec
. Es totalmente legal tomar la dirección de este elemento que no existe. Sabemos el tamaño de string
, por lo que sabemos dónde debe apuntar la dirección del sexto elemento de una matriz C-style de string
s. Siempre que solo evaluemos este puntero y nunca lo deslocalicemos, estamos bien. Incluso podemos compararlo con otros indicadores para la igualdad. El STL hace esto todo el tiempo en algoritmos que actúan sobre un rango de iteradores. El iterador end()
apunta más allá del final, y los bucles siguen formando un contador != end()
.
Ahora considere esto:
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
string myStr = "Mary";
string* myPtr = &myStr;
vector<string> myVec2(myPtr, &myPtr[1]);
copy(myVec2.begin(), myVec2.end(), ostream_iterator<string>(cout, " "));
return 0;
}
Es este código legal y bien definida? Es legal y bien definido tomar la dirección de un elemento de matriz más allá del final, como en &myAry[numStrs]
, entonces ¿debería ser legal y bien definido pretender que myPtr
también es una matriz?
+1 para precisión técnica. No solo es fácil hacer las cosas bien, sino que también se evitan otras trampas con 'operator &' sobrecargado (es malo sobrecargarlo, sí. Pero esto muestra cómo se arrastran las dependencias). Lo mejor es mantenerse libre de un comportamiento indefinido. –