Возврат указателя на элемент вектора в c ++ - PullRequest
59 голосов
/ 13 марта 2009

У меня есть вектор myObjects в глобальной области видимости. У меня есть метод, который использует std::vector<myObject>::const_iterator для обхода вектора и делает некоторые сравнения, чтобы найти конкретный элемент. Как только я нашел требуемый элемент, я хочу иметь возможность вернуть указатель на него (вектор существует в глобальной области видимости).

Если я верну &iterator, возвращаю ли я адрес итератора или адрес, на который указывает итератор?

Нужно ли привести const_iterator обратно к myObject, а затем вернуть адрес этого?

Ответы [ 9 ]

83 голосов
/ 13 марта 2009

Возвращает адрес вещи, на которую указывает итератор:

&(*iterator)

Редактировать: Чтобы устранить путаницу:

vector <int> vec;          // a global vector of ints

void f() {
   vec.push_back( 1 );    // add to the global vector
   vector <int>::iterator it = vec.begin();
   * it = 2;              // change what was 1 to 2
   int * p = &(*it);      // get pointer to first element
   * p = 3;               // change what was 2 to 3
}

Нет необходимости в векторах указателей или динамического выделения.

13 голосов
/ 13 марта 2009

Returning & iterator вернет адрес итератора. Если вы хотите вернуть способ ссылки на элемент, верните сам итератор.

Помните, что вам не нужно, чтобы вектор был глобальным для возврата итератора / указателя, но что операции в векторе могут сделать недействительным итератор. Например, добавление элементов в вектор может переместить элементы вектора в другое положение, если новый размер () больше, чем зарезервированная память. Удаление элемента перед данным элементом из вектора заставит итератор ссылаться на другой элемент.

В обоих случаях, в зависимости от реализации STL, отладка может быть затруднена, так как случайные ошибки происходят очень часто.

РЕДАКТИРОВАТЬ после комментария: «да, я не хотел возвращать итератор а) потому что его const, и б) конечно, это только локальный, временный итератор? - Краккос '

Итераторы не более или менее локальны или временны, чем любая другая переменная, и их можно копировать. Вы можете вернуть его, и компилятор сделает копию за вас, как и с указателем.

Теперь с постоянством. Если вызывающая сторона хочет выполнить модификации через возвращаемый элемент (будь то указатель или итератор), вам следует использовать неконстантный итератор. (Просто удалите const_ из определения итератора).

3 голосов
/ 13 марта 2009

Пока ваш вектор остается в глобальной области видимости, вы можете вернуть:

&(*iterator)

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

Я бы переписал это как:

myObject myFunction(const vector<myObject>& objects)
{
    // find the object in question and return a copy
    return *iterator;
}

Если вам нужно изменить возвращенный myObject, сохраните ваши значения в виде указателей и разместите их в куче:

myObject* myFunction(const vector<myObject*>& objects)
{
    return *iterator;
}

Таким образом, вы можете контролировать, когда они уничтожены.

Что-то вроде этого сломает ваше приложение:

g_vector<tmpClass> myVector;

    tmpClass t;
    t.i = 30;
    myVector.push_back(t);

    // my function returns a pointer to a value in myVector
    std::auto_ptr<tmpClass> t2(myFunction());
3 голосов
/ 13 марта 2009

Не стоит возвращать итераторы. Итераторы становятся недействительными, когда происходит изменение вектора (инверсия \ удаление). Кроме того, итератор является локальным объектом, созданным в стеке, и, следовательно, возвращение его адреса не является безопасным. Я бы посоветовал вам работать с myObject, а не с векторными итераторами.

EDIT: Если объект легкий, то лучше вернуть сам объект. В противном случае верните указатели на myObject, хранящиеся в векторе.

1 голос
/ 05 сентября 2014

Вы можете использовать функцию data вектора:

Возвращает указатель на первый элемент вектора.

Если вам не нужен указатель на первый элемент, но по индексу, то вы можете попробовать, например:

//the index to the element that you want to receive its pointer:
int i = n; //(n is whatever integer you want)

std::vector<myObject> vec;
myObject* ptr_to_first = vec.data();

//or

std::vector<myObject>* vec;
myObject* ptr_to_first = vec->data();

//then

myObject element = ptr_to_first[i]; //element at index i
myObject* ptr_to_element = &element;
0 голосов
/ 29 ноября 2014

Я не уверен, нужно ли возвращать адрес объекта, указанного итератором. Все, что вам нужно, это сам указатель. Вы увидите, что сам класс итераторов STL реализует использование _Ptr для этой цели. Итак, просто сделайте:

return iterator._Ptr;
0 голосов
/ 06 сентября 2014

Обратитесь к ответам Диркгентли и Анона, вы можете вызвать функцию front вместо begin , поэтому вы не должны написать * , но только &.

Пример кода:

vector<myObject> vec; //You have a vector of your objects
myObject first = vec.front(); //returns reference, not iterator, to the first object in the vector so you had only to write the data type in the generic of your vector, i.e. myObject, and not all the iterator stuff and the vector again and :: of course
myObject* pointer_to_first_object = &first; //* between & and first is not there anymore, first is already the first object, not iterator to it.
0 голосов
/ 13 марта 2009

Вы храните копии myObject в векторе. Поэтому я считаю, что копирование экземпляра myObject не является дорогостоящей операцией. Тогда я думаю, что самым безопасным будет вернуть копию myObject из вашей функции.

0 голосов
/ 13 марта 2009

Скажем, у вас есть следующее:

std::vector<myObject>::const_iterator first = vObj.begin();

Тогда первый объект в векторе: *first. Чтобы получить адрес, используйте: &(*first).

Однако, в соответствии с проектом STL, я бы предложил вместо этого вернуть итератор, если позже вы планируете передать его алгоритмам STL.

...