Вопрос

Рассмотрим следующий код:

#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 из strings должен указывать на.Пока мы оцениваем только этот указатель и никогда не разыменовываем его, все в порядке.Мы даже можем сравнить его с другими указателями на равенство.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 это тоже массив?

Это было полезно?

Решение

Наличие указателя на "единицу после конца" массива является законным, а не UB, и любой отдельный объект может обрабатываться так, как если бы он находился в массиве длиной 1;однако вам необходимо использовать ptr + 1 вместо этого из-за технических сложностей &ptr[1] разыменование, а затем получение адреса.Это также относится к &array[size] становление array + size.

То, что у вас есть, будет работать так, как вы ожидаете, на всех платформах, о которых я знаю, но, учитывая, насколько легко использовать однозначно правильную форму, я не вижу причин не делать этого вместо этого.

Другие советы

Стандарт C ++ в разделе 5.6 / 4 "Аддитивные операторы" гласит:

Для целей этих операторов указатель на объект, не являющийся массивом, ведет себя так же, как указатель на первый элемент массива длиной один с типом объекта в качестве типа его элемента.

Стандарт C99 6.5.6 / 7 гласит по существу то же самое.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top