Почему std :: array не имеет оператора T *? - PullRequest
0 голосов
/ 28 мая 2019

С массивами C это был тот случай, когда простое именование массива имеет тот же эффект, что и запись &foo[0] для чего-то, приближающегося к 50 годам.

При преобразовании массивов в стиле C в std :: array <>В проекте, над которым я работаю, подавляющее большинство появившихся «ошибок» было связано с вышеуказанным свойством массивов C.

Во всех случаях решение было тривиальным, просто добавьте .data().Однако мне пришло в голову, что тщательно созданный operator T* должен непосредственно решить эту проблему.

Есть ли какие-либо технические причины, по которым этот оператор не может быть создан?

Ответы [ 4 ]

5 голосов
/ 28 мая 2019

Массивы в стиле C - это размерные конструкции.Вы можете получить размер компиляции массива различными способами.Однако, когда массив превращается в указатель, вы теряете эту информацию о размерах во время компиляции.Даже если параметр имеет тип «массив», на самом деле это просто указатель без информации о размере.Вы можете использовать шаблонное программирование для сохранения размера, если массив передается в качестве параметра функции (template<size_t S> void func(T(&param)[S])), но это так.

Этот неявный распад массива на указатель считается многими программистами C ++ длябыть недостатком дизайна в массивах в стиле C.Действительно, вряд ли было бы неразумным утверждать, что преобразования с потерями, вероятно, не являются такими, которые должны быть неявными.Учитывая, что std::array является попыткой исправить как можно больше недостатков массивов в стиле C, позволить ему неявно затухать в указателе было бы контрпродуктивно.

В отличие от C++ 20 * std::span type обеспечивает неявное преобразование из std::array (и массивов в стиле C, среди прочих).Причина в том, что такое преобразование сохраняет информацию: указатель и размер.Действительно, преобразование может даже сохранить природу компиляции этого размера.


Есть ли какие-либо технические причины, по которым этот оператор не может быть создан?

" Не может не "?Нет.

1 голос
/ 28 мая 2019
* Представлено

data (), чтобы иметь одинаковый интерфейс для нескольких контейнеров STL. Например, std :: string и std :: vector также предоставляют data (), которая дает адрес фактического буфера данных. Так что интерфейс std :: array был разработан, чтобы соответствовать этому. Оператор (), который вы предлагаете, - это совсем другой способ, и он не кажется абсолютно подходящим. Как отмечалось выше, также более подходящим является оператор T * (), но все же это не то, что разработчики STL предпочитали делать - они вводили data (). Зачем? Может быть, потому что это просто более читабельно.

0 голосов
/ 28 мая 2019

Есть ли веская причина, по которой этот оператор не существует?

Если вы имеете в виду, почему нет operator T*() для автоматического предоставления приведения, одна (из нескольких) потенциальных причин именно это - идея автоматического приведения.

Может быть, было бы удобно иметь код, использующий std::array, чтобы просто правильно скомпилировать, используя operator T*(), и вы получите программу, которая была построена без ошибок. Однако есть некоторые последствия для этого:

1) Вызов operator T*() - это потенциальные затраты времени выполнения, которые программист может и не пожелать, а просто отправляется в путь. В C ++ цель состоит в том, чтобы платить только за то, что нужно, и операторы приведения просто навязывают себя, что противоречит этой идее.

2) operator T*() и операторы приведения в целом могут скрывать ошибки или узкие места в исполняемом коде из-за использования, о котором не знает программист.

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

Таким образом, гораздо безопаснее для программиста явно «преобразовывать» данные, вызывая такую ​​функцию, как data(), а не используя operator T*(), о котором они, возможно, не знали.

0 голосов
/ 28 мая 2019

Вызов data() - это то, чего вам следует избегать.Может быть полезно иметь эту силу для (как в нашем случае перенос кода или оптимизированный код, обрабатывающий кишки), однако это идет вразрез с защитной сетью, которую обеспечивает std::array.

 std::array<int, 2> a{1,2};
 auto* ptr = a.data();
 std::cout << ptr[2]; // boom

Вещи, отнимающие сеть безопасностидолжно быть явным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...