Типы, которые вы помещаете в стандартный контейнер, должны быть копируемыми и назначаемыми. Причина, по которой auto_ptr
вызывает столько проблем, заключается именно в том, что она не следует обычной семантике копирования и назначения. Естественно, все, что const
не будет назначено. Таким образом, вы не можете вставить const
ничего в стандартный контейнер. И если элемент не const
, то вы сможете его изменить.
Самое близкое решение, которое я считаю возможным, - это использовать какое-то косвенное направление. Таким образом, у вас может быть указатель на const, или у вас может быть объект, который содержит желаемое значение, но значение не может быть изменено внутри объекта (как вы получили бы с Integer
в Java).
Наличие неизменного элемента по определенному индексу противоречит принципам работы стандартных контейнеров. Возможно, вы сможете создать свои собственные, которые работают таким образом, но стандартные не делают. И ни один из них, основанный на массивах, не будет работать независимо от того, если вы не сможете уместить их инициализацию в синтаксис инициализации {a, b, c}
, поскольку после создания массива const
вы не сможете его изменить. Таким образом, класс vector
вряд ли будет работать с константными элементами независимо от того, что вы делаете.
Наличие const
в контейнере без какого-либо косвенного обращения не очень хорошо работает. Вы в основном просите сделать весь контейнер const
- что вы можете сделать, если скопируете в него из уже инициализированного контейнера, но у вас не может быть контейнера - конечно, не стандартного контейнера - который содержит константы без некоторых своего рода косвенность.
РЕДАКТИРОВАТЬ : Если вы хотите оставить контейнер в основном без изменений, но при этом иметь возможность изменять его в определенных местах кода, тогда в большинстве мест используйте const ref, а затем предоставление кода, который должен быть в состоянии изменить прямой доступ к контейнеру или неконстантная ссылка, сделает это возможным.
Итак, используйте const vector<int>&
в большинстве мест, а затем либо vector<int>&
, где вам нужно изменить контейнер, либо предоставьте этой части кода прямой доступ к контейнеру. Таким образом, он в основном неизменен, но вы можете изменить его, когда захотите.
С другой стороны, если вы хотите всегда иметь возможность изменять то, что находится в контейнере, но не изменять конкретные элементы, тогда я бы предложил поместить класс-оболочку вокруг контейнера. В случае vector
, оберните его и заставьте индексный оператор возвращать константную ссылку вместо неконстантной ссылки - либо ту, либо копию. Итак, если вы создали шаблонную версию, ваш оператор индекса будет выглядеть примерно так:
const T& operator[](size_t i) const
{
return _container[i];
}
Таким образом, вы можете обновить сам контейнер, но вы не можете изменить его отдельные элементы. И до тех пор, пока вы объявляете все функции встроенными, не должно быть большого снижения производительности (если оно вообще есть), чтобы иметь оболочку.