Как вернуть const std :: vector? - PullRequest
       39

Как вернуть const std :: vector?

1 голос
/ 15 декабря 2010

У меня есть класс с контейнером (содержащим указатель) в качестве члена:

MyClass{
private:
   std::vector<MyObject*> _VecMyObjs;
public:
   const std::vector<MyObject* const> GetVecMyObj();
}

Теперь я пытаюсь реализовать GetVecMyObj ().Вот то, что я придумал ...

const vector<MyObject *const> ACI_CALL MyClass::GetVecMyObjs()
{
   const vector<MyObject *const> VecMyObjs;
   VecMyObjs.assign( _VecMyObjs.begin(), _VecMyObjs.end());
   return VecMyObjs;
}

Но, конечно, компилятор предупреждает меня, что я использую функцию assign в const-Object.Есть лучший способ сделать это?Я имею в виду, я не хочу, чтобы VecMyObjs изменил VecMyObj вне класса, конечно.Как я могу добиться этого без предупреждения компилятора?

РЕДАКТИРОВАТЬ: Хорошо.Спасибо всем.Теперь это так:

const vector<MyObject *const> ACI_CALL MyClass::GetVecMyObjs()
{
   const vector<MyObject *const> VecMyObjs;
   VecMyObjs.assign( _VecMyObjs.begin(), _VecMyObjs.end());
   return VecMyObjs;
}

Но я не могу обойти функцию присвоения, верно?Например, приведение «оригинала» не работает, если я хочу, чтобы «все» было постоянным.

Ответы [ 5 ]

3 голосов
/ 15 декабря 2010

Я не уверен, что std::vector<MyObject * const> (вектор указателей констант) действительно то, что вы хотите: я полагаю, вы имеете в виду std::vector<MyObject const *> (вектор указателей на константные объекты).

  1. «Первый уровень» константности ( указатель константности) естественным образом достигается путем возврата постоянной ссылки на вектор. Из константного вектора можно получить только const_iterator, так что у вас есть гарантия, что указатели не будут изменены (но pointees может быть).

  2. «Второй уровень» постоянства ( pointee constness) получить сложнее. Либо верните новый экземпляр вектора, как уже было указано другими:

    return std::vector<const MyObject *>(_VecMyObjs.begin(), _VecMyObjs.end());
    

    Или, если применимо, попробуйте заглянуть в библиотеку Boost Pointer Container (и особенно ptr_vector ), которая предлагает, среди прочего, правильное распространение константности:

    Распространяет константу так, чтобы не может изменить объекты с помощью const_iterator.

Вы должны понимать, что возврат константной ссылки на вектор гарантирует, что он не может быть изменен (без вставки, удаления или изменения его значения). Таким образом, в большинстве случаев возвращение const std::vector<T> & - это путь, потому что если не включает в себя копирование. Проблема здесь действительно специфична для контейнера указателей, где константность значений не обеспечивает константу указателей.

2 голосов
/ 15 декабря 2010

Если вы хотите вернуть новый vector, не делайте этого const. Поставьте ключевое слово const перед *.

std::vector<MyObject const*> MyClass::GetVecMyObj()
{
    return std::vector<MyObject const*>(_VecMyObjs.begin(), _VecMyObjs.end());
}

Я опустил преобразование в TRoadSgmt, поскольку вы не указали наследование этого класса.

1 голос
/ 15 декабря 2010

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

Адрес первого элемента вектора будет T **, и выне может привести это к const T ** (правильно), и вы не можете привести его к const T * const * (что было бы безопасно, но язык не позволяет).

Если бы вам было разрешено конвертироватьпоследнее было бы идеально для создания представления только для чтения.

0 голосов
/ 15 декабря 2010
const vector<const MyObject *> MyClass::GetVecMyObjs() const
{
   return vector<const MyObject *>(_VecMyObjs.begin(), _VecMyObjs.end());
}

Это, кажется, решение для меня. Я могу сказать сейчас, благодаря всем различным постам, которые я получил. Спасибо всем вам! Хорошего вам ... (Или дайте мне знать, если я все еще где-то не прав.)

0 голосов
/ 15 декабря 2010

Помимо изменения подписи для удаления const из vector (поскольку это копия вектора), я предполагаю, что в результате вы не хотите, чтобы люди снаружи изменяли содержимое, сделать указатель const, т.е.

vector<const MyObject *> ACI_CALL MyClass::GetVecMyObjs()
{
   return vector<const MyObject *>(_VecMyObjs.begin(), _VecMyObjs.end());
}

Теперь возвращаемый вектор является копией, которая содержит указатель const (что означает, что вы не можете изменить указанный объект с помощью этого указателя) - ну, это соглашение, ничто не мешает кому-то const_cast удалить это (используя В любом случае это UB!)

Если вы действительно хотите предотвратить изменения, верните копию (или клон каждого объекта) в вектор.

...