2013-10-02 2 views
3

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

Мне нравится использовать вектор твердых элементов, как std::vector<MyObject> vec, потому что:

  • станд :: вектор сделать все выделения/открепления вещи для меня
  • также гарантирует мне, что мои элементы хранятся в непрерывной памяти
  • я могу получить преимущества всего кода, которые работают с векторами (например, <algorithm>)

Это именно то, что я хочу. Проблема возникает, когда я хочу сохранить адрес/ссылку элементов моего вектора в других объектах. На самом деле проблема действительно возникает, когда std :: vector должен перераспределять память.

Я пытался найти альтернативу моей проблеме:

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

  • использовать векторные указателей/умных указателей и напишите мой собственный оператор new/new [] для MyObject: Humm, это кажется лучше, но нет. Используя вектор для выделения моих элементов, я могу сказать: «Эти конкретные элементы (я не ссылаюсь здесь на std::set) элементов должны быть выделены смежно, а не все». На самом деле, я могу захотеть иметь другой набор элементов, которые должны быть распределены смежно из-за того, как я хочу их использовать, и используя вектор для этого, это именно то, что (я думаю) мне нужно. То также подразумевает, что я выполняю работу, которую хочу, чтобы вектор выполнял.

  • Почему бы не использовать boost multi-index? : В некотором роде это будет делать то, что я хочу, потому что я хочу хранить указатели/смарт-указатели моих векторных элементов в других контейнерах. Но нет снова, потому что я действительно хочу хранить reference/pointer/smartpointer элементов моего вектора внутри других объектов, а не только других контейнеров.

Что бы я любил, чтобы вектор, который может дать мне объект указатель, который будет ВСЕГДА указывать на адрес нужного элемента и я буду использовать его так:

std::vector<MyObject> vec; 
// insert some elements 
... 
// get a pointer object by index or by using an iterator 
// does something like that exist? 
std::vector<MyObject>::pointer ptr = vec.get_pointer_at(5); 

// do what I want on the vector except removing the element 
... 

// use my pointer whatever reallocations occurred or not 
ptr->doSomething(); 

Это звучит как итератор, который никогда не будет признан недействительным, за исключением того факта, что мне не нужно/не нужно выполнять арифметику (+ x, -x, ++, -).

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

Edit:

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

+0

Если вам нужно изменить содержимое вектора, вам придется сменить контейнер. Если вы меняете только содержимое вектора, но не размер, тогда вы должны быть в порядке. – RedX

+0

Лоран, вы считали «deque»? – ArtemGr

+3

Что касается написания итератора, который не является недействительным. Храните индекс внутри итератора вместо адреса элемента. – cdoubleplusgood

ответ

2

Хотя std::vector не дает вам такого указателя, нет причин, по которым вы не можете сделать это самостоятельно. Все, что требуется, это класс, который содержит ссылку на объект и индекс std::vector и overloads префикс operator * и инфикс operator -> (для каждого оператора требуется четыре перегрузки - const и не const).

Вы могли бы использовать этот указатель, как это:

std::vector<int> vect = {2, 4, 6, 8, 10, 12, 14, 16}; 
vect_ptr<int> ptr(vect, 5); // <<== You need to implement this 
*ptr = 123; 
cout << *ptr << endl; 

Реализация этих перегрузках бы захватить std::vector «s begin() итератор, и возвращает результат вызова vect.at(index). Это будет выглядеть как указатель снаружи, но объект, на который он указывает, изменится по мере изменения размера содержимого std::vector.

+0

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

+1

@ Laurent: Я подозреваю, что вы хотите Неправильную вещь. Возможно, если вы расскажете нам больше о том, почему вы думаете, что вам нужно это ... –

+0

Это повторяющаяся проблема, с которой я сталкиваюсь: у меня есть коллекция объектов, и мне нравится способ, которым вектор может управлять процессом распределения. Я также доволен операциями, которые могут выполняться на контейнерах stl. – Laurent

0

Насколько я знаю, в стандартной библиотеке и в Boost нет ничего, чтобы решить вашу проблему. Решением было бы реализовать свой собственный указатель на элемент:

template<typename T> 
class vector_element 
{ 
public: 
    vector_element(std::vector<T>& v, std::size_t i) 
     : m_container(v), m_element_index(i) 
    { } 

    T& operator*() { return m_container[m_element_index]; } 
    T* operator->() { return &m_container[m_element_index]; } 
private: 
    std::vector<T>& m_container; 

    std::size_t m_element_index; 
}; 
+0

Прости, Жюльен, но я не упоминал, что индекс элемента не меняется. Фактически, вставки могут привести к недействительности вашего значения индекса, поэтому ваше решение не подходит – Laurent

+0

ОК, я понял, что вы все предлагаете использовать индекс и избегать делать вставки (кроме push_back), я буду больше думать об этом решении. – Laurent

Смежные вопросы