const_cast для вектора с объектом - PullRequest
1 голос
/ 06 января 2009

Я понимаю, что const_cast для удаления констант объектов плох,

У меня есть следующий вариант использования,

//note I cannot remove constness in the foo function
foo(const std::vector<Object> & objectVec) {

   ...
   int size = (int) objectVec.size();
   std::vector<Object> tempObjectVec;
   //Indexing here is to just show a part of the vector being
   //modified
   for (int i=0; i < (int) size-5; ++i) {
       Object &a = const_cast<Object&> objectVec[i];
       tempObjectVec.push_back(a);
   } 
   foo1(tempObjectVec);
}  

Если я изменю объекты tempObjectVec в foo1, изменится ли исходный объект в ObjectVec, я говорю да, так как я передаю ссылки, в дальнейшем это эффективно. Можете ли вы предложить альтернативы.

Ответы [ 4 ]

3 голосов
/ 06 января 2009

Ну, это зависит от объекта. Но объекты копируются , когда вы передаете их push_back. Вы можете проверить это, добавив некоторый отладочный код в конструктор копирования. Таким образом, если Object хорошо себя ведет и хранит отдельные копии отдельно, то foo1 может изменить вектор, который он получает, как ему угодно.

Более эффективный способ сделать это - заставить foo1 принять итераторы начала и конца:

void foo1(std::vector<Object>::const_iterator start,
          std::vector<Object>::const_iterator end);

...
foo1(objectVec.begin(), objectVec.end() - 5);

Если вы не используете const_cast, то система типов гарантирует, что foo1 не изменит никаких элементов, поскольку они являются const_iterators.

1 голос
/ 06 января 2009

Как уже говорят другие, push_back вашего вектора получает ссылку, но затем копирует объект, на который ссылается. Итак, в конце вы получите копию objectVec[i] в вашем tempObjectVec.

Вектор не может хранить ссылки, потому что они не могут быть назначены (присваивания ему влияют не на саму ссылку, а на объект, на который она ссылается), что является требованием для объектов, которые должны храниться в векторе. Ссылки также не являются объектами. У них нет собственного размера. Поэтому они не могут быть помещены в массив или любой вектор. Обычно вы хотите хранить указатели или умные указатели в таком контейнере для ссылки на какой-либо другой объект. Посмотрите на библиотеку boost pointer container, которая выглядит именно так, как вы хотите.

1 голос
/ 06 января 2009

Я считаю, что это заявление, которое вы ищете:

const_cast<std::vector<Object>&> (objectVec) это вернет ссылку на неконстантный std::vector, который должен быть приемлемым для foo1 (я предполагаю).

Изменение исходного примера:

foo(const std::vector<Object> & objectVec) {

    ...
    foo1(const_cast<std::vector<Object> &>(objectVec));
}

Однако я рекомендую взглянуть на фактические требования foo1, которые требуют от него использования неконстантного вектора, поскольку вы, похоже, указываете, что все, что вас интересует, - это изменение самих Object экземпляров.

1 голос
/ 06 января 2009

Ваш tempObjectVec не может быть вектором ссылок, поэтому я предполагаю, что он должен быть объявлен как что-то вроде:

std::vector<Object> tempObjectVec;

Когда вы выполните tempObjectVec.push_back(a), будет сделана копия объекта, чтобы протолкнуть его в вектор tempObjectVec. Так как это делает копию, вам даже не нужно использовать const_cast для удаления константности, я не понимаю, зачем вам это нужно было делать.

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