2017-01-12 3 views
0

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

void addPtrs(vector<Thing*> & ThingPtrs, const vector<Thing> & actualThings) { 
     for (const Thing & t : actualThings) 
      if (/*some condition*/) 
       ThingPtrs.push_back(&t); 
} 

В принципе, я хочу изменить ThingPtrs, давая это указатели на Thing с, которые имеют какое-либо условие. Однако, поскольку я не хочу изменять фактический Thing, я помечен как actualThings как const, и теперь я не могу назначить указатель const указателю не const.

Очевидно, что одним из решений является просто не делать actualThingsconst, но я на самом деле не намерен его изменять. Другое решение использует const_cast, но я хотел бы избежать этого, если это возможно.

Каковы мои варианты в такой ситуации?

+0

Если вы не намерены изменять любой 'Thing', ваш' ThingPtrs' будет определяемый как 'std :: vector &'. Увидев, что в нем хранятся указатели, отличные от 'const', это означает, что в какой-то момент требуется некоторая модификация _will_, поэтому вам не нужна никакая 'const'ness. –

+0

Я намерен изменить 'Thing', но только через' actualThings' isntead 'ThingPtrs'. Могу ли я определить 'ThingPtrs' типа' vector '? – Dillydill123

+0

@ Dillydill123 Да, если вы измените 'ThingPtrs' на' vector ', тогда ваша функция должна скомпилироваться. –

ответ

2

По дизайну const std::vector не позволит вам напрямую изменять его элементы. Поскольку actualThings const, вы не можете изменять его содержимое. Любая ссылка или указатель на ее элементы будет const.

Любое решение, которое вы обнаружите, не изменяя прототип функции, в конечном счете будет включать преобразование const Thing & или const Thing * в неконстантный эквивалент, независимо от того, как вы его одеваете. Любой указатель или реинтерпретация указателя будет всего лишь округлять до const_cast.

Если вы обеспокоены тем, что addPtrs не изменяет actualThings (в смысле вызова его неконстантного элемента), вы можете изменить свой интерфейс, чтобы принять пару итераторов начала и конца. Другие изменения, которые позволят вашей функции компиляции включают удаление сопзЬ от actualThings получить vector<Thing> & actualThings или добавление сопзЬ к типу элементов в ThingPtrs, чтобы получить vector<const Thing*> & ThingPtrs

+0

Итак, я попробовал 'vector ', и я удивлен, что это скомпилировано. Как это разрешено, учитывая, что когда «вектор» достигает емкости, он должен переделать свой контейнер? Я также заметил, что 'vector ' не компилируется. – Dillydill123

+1

@ Dillydill123 Этот подход не защищает от недействительности. Он действительно сломается, если/когда изменяется значение 'actualThings'. Все указатели и ссылки на элементы вместе со всеми итераторами недействительны, когда это происходит. Указатель const ** не гарантирует, что указанный объект не может быть изменен **, только если вы не можете изменить его с помощью указателя. Для вашего другого вопроса см. [Этот вопрос] (http://stackoverflow.com/questions/1143262/what-is-the-difference-between-const-int-const-int-const-and-int-const) для больше информации о разных местах, где вы можете поместить const по типу указателя. –

+0

@ Dillydill123 для вашего второго вопроса в комментарии, просто чтобы убедиться, что вы знаете разницу между 'const X *'/'X const *' vs 'X * const' right? (указатель на const X vs const указатель на X) –