Рассматривать
int main()
{
auto a = new int[0];
delete[] a; // So there's no memory leak
}
Между инициализацией и удалением копии вы можете читать указатель на a + 1
?
Кроме того, позволяет ли язык компилятору установить a
значение nullptr
?
c++
language-lawyer
Вирсавия
источник
источник
a
наверняка (вы, конечно, не можете разыменовать его).a + 1
», следующий код являетсяauto b = a + 1;
неопределенным поведением? (Я думаю, что это).0
на самом деле это результат выражения, которое вы не узнаете до времени выполнения. Так какnew int[0]
это безопасно, это может избавить вас от беспокойства о некоторых ветвлениях / особых случаях. Представьте себе, если бы я должен был инициализироватьstd::vector
сstd::vector<int> v(0);
.Ответы:
Согласно [basic.compound.3] , значение, хранимое в,
a
должно быть одним из следующих:int
)Мы можем исключить первую возможность, так как не было построено объектов типа
int
. Третья возможность исключена, поскольку C ++ требует, чтобы возвращался ненулевой указатель (см. [Basic.stc.dynamic.allocation.2] ). Таким образом, у нас остается две возможности: указатель за концом объекта или неверный указатель.Я был бы склонен рассматривать
a
как указатель "за конец", но у меня нет авторитетной ссылки, чтобы окончательно установить это. (Однако в [basic.stc] есть сильное следствие этого , видя, как вы можете использоватьdelete
этот указатель.) Поэтому в этом ответе я рассмотрю обе возможности.Поведение не определено, как предписано [expr.add.4] , независимо от того, какая возможность сверху применима.
Если
a
указатель конца-конца, то считается, что он указывает на гипотетический элемент по индексу0
массива без элементов. Добавление целого числаj
кa
определяется только тогда0≤0+j≤n
, когда , гдеn
это размер массива. В нашем случаеn
это ноль, поэтому суммаa+j
определяется только тогда, когдаj
есть0
. В частности, добавление1
не определено.Если
a
недействительно, то мы чисто попадаем в «В противном случае, поведение не определено». (Не удивительно, что определенные случаи охватывают только допустимые значения указателя.)Нет. Из вышеупомянутого [basic.stc.dynamic.allocation.2] : «Если запрос выполняется успешно, значение, возвращаемое заменяемой функцией распределения, является ненулевым значением указателя» . Существует также сноска, в которой говорится, что C ++ (но не C) требует ненулевого указателя в ответ на нулевой запрос.
источник
Согласно недавнему обсуждению рефлектора CWG в результате редакционной проблемы 3178 ,
new int[0]
получается то , что в настоящее время называется значением указателя «конец конца» .Отсюда следует, что
a
не может быть нулевым иa + 1
не определено [expr.add] / 4 .источник
new int[0]
получается то , что в настоящее время называется значением указателя« конец конца »». Это не точно. Там не было много дискуссий. Один человек предложил, чтобы значением было «указатель за концом объекта», и это утверждение было подвергнуто сомнению, потому что в случае массива с0
элементами не существует объекта, который должен быть после конца.a + 1
в любом случае не определено, так что ваша точка зрения относится только к тому,a
может ли быть NULL?a + 1
это не определено, и, возможно, полученное значение указателя будет называться «указатель за концом». Я не говорю, что ответ неправильный. Это немного не точно, потому что это можно понять как длительное обсуждение с консенсусом, что достаточно просто указать, что результатом является «указатель на конец», чтобы решить проблему. Проблема с «указателем за концом» состоит в том, что он находится за концом некоторого объекта, и вычитание1
из такого значения указателя дает один указатель на объект, что, вероятно, не должно иметь место для массивов0
элементов.