Могу ли я использовать const в векторах, чтобы разрешить добавлять элементы, но не изменять уже добавленные? - PullRequest
60 голосов
/ 03 мая 2010

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

#include <vector>

int main() {
    std::vector <const int> v;  
}

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

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

vector <const int> v;     // ok (i.e. I want it to be OK)
v.push_back( 42 );        // ok
int n = v[0];             // ok
v[0] = 1;                 // not allowed

Ответы [ 14 ]

0 голосов
/ 30 сентября 2016

Компиляция не удалась, потому что push_back() (например) в основном

underlying_array[size()] = passed_value;

где оба операнда T&. Если T равно const X, это не может работать.

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

0 голосов
/ 03 мая 2010

std::vector константного объекта, вероятно, не удастся скомпилировать из-за требования Assignable, так как константный объект не может быть назначен. То же самое относится и к назначению движения. Это также проблема, с которой я часто сталкиваюсь при работе с векторной картой, такой как boost flat_map или Loki AssocVector. Так как имеет внутреннюю реализацию std::vector<std::pair<const Key,Value> >. Таким образом, практически невозможно выполнить постоянное ключевое требование карты, которое может быть легко реализовано для любой карты на основе узлов.

Однако можно посмотреть, означает ли std::vector<const T>, что вектор должен хранить типизированный объект const T, или ему просто нужно вернуть неизменяемый интерфейс при доступе. В этом случае возможна реализация std::vector<const T>, которая следует требованию Assignable / Move Assignable, поскольку в нем хранится объект типа T, а не const T. Стандартные typedefs и тип распределителя нужно немного изменить, чтобы поддерживать стандартные требования. Несмотря на то, что для поддержки такого типа vector_map или flat_map, вероятно, требуется значительное изменение в интерфейсе std::pair, так как он первым и вторым предоставляет переменные-члены напрямую .

0 голосов
/ 03 мая 2010

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

0 голосов
/ 03 мая 2010

Используя только неспециализированный vector, этого сделать нельзя. Сортировка осуществляется с помощью присваивания. Итак, тот же код, который делает это возможным:

sort(v.begin(), v.end());

... также делает это возможным:

v[1] = 123;

...