Подтвердить что ты не робот

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

Это хороший старый массив C:

int a[10];

И это хороший старый массив C, который const:

const int b[10];

В С++ существует два способа определить std::array, которые const:

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

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

4b9b3361

Ответ 1

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

1

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

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

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

2

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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