Должен ли я вернуть итератор или указатель на элемент в контейнере STL? - PullRequest
5 голосов
/ 13 сентября 2010

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

Следующие определения взяты из API:

typedef unsigned long shape_handle;    
shape_handle make_new_shape( int type );

Мне нужно переопределить make_new_shape, и у меня есть возможность переопределить shape_handle.

Я определил эту структуру (упрощенно):

struct Shape
{
    int type
};

Вызывающий объект make_new_shape не заботится о базовой структуре Shape, ему просто нужен «дескриптор», чтобы он мог вызывать такие функции, как:

void `set_shape_color( myshape, RED );`

где myshape - указатель на фигуру.

Мой движок будет управлять памятью для объектов Shape, а другие требования диктуют, что движок должен хранить Shape объекты в списке или другом итерируемом контейнере.

У меня вопрос, какой самый безопасный способ представить этот дескриптор - если сам Shape будет храниться в std :: list - итератор, указатель, индекс?

Ответы [ 4 ]

6 голосов
/ 13 сентября 2010

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

Итак, если вы просто хотите получить доступ к своей фигуре, указатель будет самым простым. Если вы хотите перебрать свой список, используйте итератор.

Индекс в списке бесполезен, поскольку std :: list не перегружает оператор [].

3 голосов
/ 13 сентября 2010

Итераторы не безопаснее, чем указатели, но они имеют намного лучшую диагностику, чем необработанные указатели, если вы используете проверенную реализацию STL!

Например, в отладочной сборке, если вы возвращаете указатель на элемент списка, а затем удаляете этот элемент списка, у вас есть висячий указатель. Если вы получаете доступ к нему, вы получаете сбой, и все, что вы можете увидеть, это ненужные данные. Это может затруднить понимание того, что пошло не так.

Если вы используете итератор и у вас есть проверенная реализация STL, как только вы получаете доступ к итератору для стертого элемента, вы получаете сообщение, похожее на «итератор был признан недействительным». Это потому, что вы стерли элемент, на который он указывает. Бум, ты только что спас себе потенциально много усилий по отладке.

Итак, не показатели для O (n) производительности. Между указателями и итераторами - всегда итераторами!

3 голосов
/ 13 сентября 2010

Ответ зависит от вашего представления:

  • для std::list, используйте iterator (не указатель), потому что iterator позволяет удалить элемент, не просматривая весь список.
  • для std::map или boost::unordered_map, используйте Key (конечно)

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

Попробуйте сравнительный анализ map и unordered_map, чтобы определить, какой из них быстрее в вашем случае:)

3 голосов
/ 13 сентября 2010

IIF внутренним представлением будет список форм, тогда указатели и итераторы безопасны.Как только элемент выделен, перемещение никогда не произойдет.Я бы не рекомендовал индекс по очевидным причинам производительности доступа.O (n) в случае списков.

Если вы использовали вектор, не используйте итераторы или указатели, потому что элементы могут перемещаться, когда вы превышаете емкость векторов, и ваши указатели / итераторы станутНеправильно.

Если вы хотите, чтобы представление было безопасным независимо от внутреннего контейнера, создайте контейнер (список / вектор) указателей на ваши фигуры и верните указатель формы вашему клиенту.Даже если контейнер перемещается в памяти, объекты Shape останутся в том же месте.

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