постоянные массивы - PullRequest
       16

постоянные массивы

20 голосов
/ 17 октября 2011

Это старый добрый массив C:

int a[10];

А это старый добрый массив C, который const:

const int b[10];

В C ++, кажется, есть два способа определить std::array s, которые const:

std::array<const int, 10> c;
const std::array<int, 10> d;

Являются ли эти два определения эквивалентными? Если это так, что является идиоматическим? Если нет, в чем различия?

Ответы [ 3 ]

12 голосов
/ 17 октября 2011

Ну, а исходный const int b[10]; полезен только тогда, когда вы можете инициализировать массив, так что оба примера std::array на практике не работают.

1

std::array<const int, 10> c;

Это самый близкий к const int c[10];. Проблема в том, что для него не будет конструктора по умолчанию, и поскольку элементы не являются изменяемыми, использовать это бесполезно. Вы должны обеспечить некоторую инициализацию для этого в конструкторе. Как есть, он выдаст ошибку компилятора, потому что конструктор по умолчанию не инициализировал элементы.

Этот код означает, что c является изменяемым, но сами элементы не являются. На практике, однако, на c нет мутаций, которые не влияют на элементы.

2

const std::array<int, 10> d;

Это означает, что d не является изменяемым, но элементы имеют изменяемый тип int. Поскольку const будет распространяться на элементы, это означает, что элементы все еще не изменяются вызывающей стороной. Как и в приведенном выше примере, вам нужно будет инициализировать d, потому что это const.

На практике они оба будут вести себя одинаково в отношении изменчивости, потому что изменяемые операции на array всегда касаются элементов.

6 голосов
/ 17 октября 2011

Они не эквивалентны - c.reference - это int&, тогда как d.reference - это const int& (не то, чтобы вы могли использовать этот синтаксис для доступа к typedefs, но вы могли бы захватить тип с помощью вывода аргумента шаблона и сообщитьРазница).

Но я уверен, что у Тенфура есть ключевое замечание: «На c нет мутаций, которые не влияют на элементы».Итак, что касается всего, что вы на самом деле делаете с массивами, они одинаковы, у них просто разные метаданные из-за их разных типов.

Основной случай, который я могу придумать, гдеРазница заключается в том, что вы используете сам тип в интерфейсе (в отличие от параметра итератора или шаблона диапазона).Я бы сказал, что, принимая его в качестве указателя или ссылочного параметра, вы должны const-квалифицировать сам тип array, поскольку он ничего не стоит и позволяет вызывающей стороне использовать вашу функцию независимо от того, какой выбор они сделали.Вы можете const-квалифицировать тип элемента, но какой бы из них вы ни использовали, он несовместим с другим, поэтому в основном каждый должен договориться о том, какой использовать, иначе потребуется копирование.Это требует активной координации в отношении стиля, я думаю, так как я сомневаюсь, что вы заставите всех в мире согласиться, что лучше.const int, вероятно, имеет лучший случай, по принципу, что вы должны const все, что можете, но я ожидаю, что int - это то, что будут использовать люди, которые вообще не думали об этом, поскольку они привыкли ко всемте контейнеры C ++ 03, которые не могут иметь тип значения const.

5 голосов
/ 17 октября 2011

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

const std::array<const int,10> c;

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

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