Рассмотрим следующий код:
#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;
}
Интерес представляет здесь &myAry[numStrs]
: numStrs равно 5, поэтому &myAry[numStrs]
указывает на то, чего не существует; шестой элемент в массиве. В приведенном выше коде есть еще один пример этого: myVec.end()
, который указывает на один конец конца вектора myVec
. Совершенно законно брать адрес этого элемента, который не существует. Мы знаем размер string
, поэтому мы знаем, куда должен указывать адрес 6-го элемента массива в стиле C string
s. Пока мы только оцениваем этот указатель и никогда не разыменовываем его, мы в порядке. Мы можем даже сравнить его с другими указателями на равенство. STL делает это все время в алгоритмах, которые действуют на целый ряд итераторов. Итератор end()
указывает за конец, и циклы продолжают циклировать, пока счетчик != end()
.
Теперь рассмотрим это:
#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;
}
Является ли этот код законным и четким? Законно и четко определено брать адрес элемента массива после конца, как в &myAry[numStrs]
, поэтому должно ли быть законно и четко определено, что myPtr
также является массивом?