Dynami c массивы в C ++ без неопределенного поведения - PullRequest
3 голосов
/ 02 марта 2020

Узнав, что std :: vector невыполнимо в чистом C ++, мне стало интересно, можно ли написать динамический массив c без вызова UB. Мы не можем сделать арифметику указателей c без массива , что означает, что мы не можем иметь динамический буфер c с частично инициализированной памятью и рассматривать его как массив; поэтому std :: vector должен опираться на реализацию, определяющую некоторое поведение, где в противном случае это было бы UB.

Dynami c Массивы - это довольно распространенные структуры данных, и, как правило, простые. Кажущаяся невозможность реализовать это соответствующим образом делает C ++ похожим на системный язык не столь общего назначения, IMO.

Поэтому мои вопросы таковы:

  • Как Можно написать динамический c массив (обычный, не обязательно Контейнер) в C ++ (без использования std :: vector), который соответствует стандарту?
  • Как сделать такую ​​реализацию в пространстве-времени эффективный (предпочтительно без UB или специфика реализации c поведение)?

NB: dynamici c массив используется здесь для обозначения линейной структуры данных, которая может увеличиваться / уменьшаться «на месте», как std :: vector или, аналогично, C буфер (m), выделенный в куче.

Ответы [ 2 ]

7 голосов
/ 02 марта 2020

Если std::vector не может, то и вы не можете.

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

Теперь, ключ: это не из-за магических c, присущих std::vector или какой-то конкретной реализации std::vector: это потому, что компилятор не выполняет абсурдные оптимизации которые используют это неопределенное поведение, которое кто-то только что заметил при изучении текста с мелкими зубьями.

Возможно, оно будет приведено в порядок в будущей редакции , но для практического применения. целей вам не нужно беспокоиться об этом, используете ли вы std::vector или new[].

5 голосов
/ 02 марта 2020
Массив

dynamici c используется здесь для обозначения линейной структуры данных, которая может увеличиваться / уменьшаться «на месте»,

Вы не можете. Именно рост / сжатие на месте делает vector невыполнимым в C ++ 17.

Проблема в том, что объектная модель C ++ 17 распознает «массив» как вещь, особый объект Тип со своими свойствами. Арифметика указателя c распознает массивы и работает в них. Но у «массива» есть указанное c количество элементов, и простое создание живого объекта типа элемента массива в конце массива на самом деле не делает массив длиннее. Это означает, что арифметика указателя c не работает для доступа к этому вновь созданному объекту.

Эта проблема не исчезает go только потому, что вы изменили оболочку. Это проблема, которая является фундаментальной для идеи возможности сделать массив больше и меньше, при этом все еще имея арифметику указателей c.

...