2017-01-25 13 views
0

Компонент Собственный набор, содержащий указатели, я планирую создать API для возврата набора. В настоящее время другой компонент только читает содержимое набора, не намерен ничего менять, и я должен вернуться из API.C++ STL, что мне вернуть запрос для List/Set?

Варианты: 1. Вернуть копию набора 2. Вернуть ссылка набора 3. Возвращение пара итератора множества. std:pair<ForwardIterator begin, ForwardIterator end>

Концерн: 1. Возможно, некоторые накладные расходы для копирования. 2. Это выставляет внутренний набор, он не может остановить другие компоненты, чтобы изменить его. 3. Если компонент A изменит набор, будет ли он недействителен итератором?

+1

Что нужно пользователям API? Должны ли они даже знать, что это набор? – doctorlove

ответ

0

На данный момент давайте предположим, что вы уверены в этом: ComponentA владеет набор указателей, std::set<Thing *>, и вы хотите, чтобы иметь метод, чтобы вернуть этот набор, но так, что принимающий клиентский код не может изменить Это. Вы не уверены в следующем:

  1. Верните копию комплекта.
  2. Верните ссылку на комплект.
  3. Возврат [begin(), end()).

Не делайте этого. У каждого есть недостаток, который вы идентифицировали, и имеет дополнительный недостаток, который он не возвращает набор. Клиент код, получающий диапазон итераторов, не будет знать, что он ограничивает набор и не сможет воспользоваться определяющими свойствами набора.

Вместо возврат const ссылки на набор из метода const:

struct ComponentA 
{ 
    ... 
    ... 
    std:set<Thing *> const & get_set_of_things() const { 
     return things; 
    } 
private: 
    std::set<Thing *> things 
    ... 
}; 

Это устраняет недостаток - клиентский код не может изменить набор через в const ссылки - и не имеет никаких других помех.

Я надеюсь, что ответит на ваш вопрос, , но я боюсь, что это еще не конец ваших проблем с дизайном.

Код клиента не может изменить things через std:set<Thing *> const &, возвращенный get_set_of_things(). Но вещи, которые я не могу изменить, являются членами этого набора, которые всего лишь указатели до Thing. Мне, конечно, все равно, что эти указатели - адреса памяти, такие как 0x1a04c20 - и я не заинтересован в изменении их. Но ничего останавливает меня от изменения любого из Things, что эти указатели указывают на, например.

ComponentA ca; 
... 
auto const & things = ca.get_set_of_things; 
Thing * pthing = *things.begin(); 
thing->modify(); 
... 

Это изменяет один из Things контролируемой ca - что то, что вы хотите предотвратить.

Однако вы возвращаете набор из ComponentA объекта, вы не можете предотвратить клиента от модификации Things под контролем объекта до тех пор, как вы даете им Thing * -pointers.

Ну вы могли бы блокировать эту угрозу путем изменения things к набору const указателей:

struct ComponentA 
{ 
    ... 
    ... 
    std:set<Thing const *> const & get_set_of_things() const { 
     return things; 
    } 
private: 
    std::set<Thing const *> things 
    ... 
}; 

Но выпадению этого изменения является то, что в настоящее время ComponentA сама не может изменять любого из Things контролируется things. Можете ли вы с этим жить?

И это только первый из нескольких громких дизайнерских тревог, которые вызываются информацией, что ваш ComponentA контролирует набор указателей. Я предлагаю вам создать определение вашего класса и поставить его для комментария на сайте-партнере SO Code Review. Это выходит за рамки SO, чтобы исследовать все вероятные подводные камни, особенно при отсутствии какого-либо кода.

+0

Майк: Ты совершенно прав. Вернуть ссылку const будет лучшим выбором для нее. И я могу жить с установленным удержанием Thing * pointer в настоящее время. – user7469511