C ++ Использует ли ссылки auto_ptr как переменные вне идиоматических? - PullRequest
3 голосов
/ 15 июля 2011

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

bool MakeEm(auto_ptr<Foo>& outFoo, auto_ptr<Bar>& outBar) {
  ...
  if (...) {
    return false;
  }
  outFoo.reset(new Foo(...));
  outBar.reset(new Bar(...));
  return true;
}

Это позволяет вызывающей стороне сделать это:

auto_ptr<Foo> foo;
auto_ptr<Bar> bar;
MakeEm(foo, bar);

Мой вопрос: «Это идиоматизм? Если нет, как правильно это сделать?»

Альтернативные подходы, которые я могу придумать, включают возвращение struct из auto_ptr s или написание API-интерфейса фабрики для получения необработанных ссылок на указатели. Они оба требуют написания большего количества кода, и у последнего есть другие проблемы, когда речь идет о безопасности исключений.

Ответы [ 5 ]

4 голосов
/ 15 июля 2011

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

  1. Вы возвращали один объект вместо 2. Если вам нужны два тесно связанных объекта, которые не могут существовать друг без друга, я бы сказал, что у вас сильныйкейс для is-a или has-refactoring.
  2. Это C ++.Действительно спросите себя, должны ли вы возвращать значение, указывающее на успех, заставляя потребителя вашего завода каждый раз проверять.Бросайте исключения или передавайте исключения из конструкторов ваших классов на фабрике.Хотели бы вы когда-нибудь быть в порядке с false и попытаться оперировать неинициализированным auto_ptr?
1 голос
/ 16 июля 2011

Вам не нужно создавать собственную структуру для возврата двух значений - вы можете использовать std :: pair.В этом случае нет большой синтаксической нагрузки при возврате двух значений.Это решение имеет проблему, заключающуюся в том, что «.first» и «.second» не очень описательные имена, но если используемые типы и имя функции проясняют намерение достаточно ясно, то это не обязательно проблема.1002 * Если вы используете C ++ 0x, вы можете использовать unique_ptr вместо auto_ptr, и вызывающая сторона может использовать auto вместо необходимости вводить более длинный std :: pair,Если вы не используете C ++ 0x, вы можете использовать вместо этого typedef.

Если вы вернете два значения, у вас не будет места для bool.Вы можете использовать кортеж C ++ 0x для возврата всех трех значений.Вы также можете указать ошибку, выбрасывая исключение или возвращая нулевые указатели.Я бы предпочел исключение, предполагая, что ошибка редкая / исключительная.

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

1 голос
/ 15 июля 2011

Предположим, что возвращаемое значение false означает «не смотрите на выходные параметры».

Тогда я бы избавился от возвращаемого значения bool, вернул структуру или паруу которого есть нужные auto_pointers и throw в состоянии ошибки.

1 голос
/ 15 июля 2011

Обычно, когда у вас есть параметры auto_ptr, они не являются ссылками.

Это потому, что когда вы передаете что-то функции, которая принимает auto_ptr, вы ожидаете, что эта функция станет владельцем. Если вы передаете по ссылке, он фактически не берет объект (он может взять объект).

Это тонкий момент, но, в конце концов, вам нужно посмотреть, что ваш интерфейс пытается сказать пользователю.

Также вы, похоже, используете его в качестве параметра out .
Лично я никогда не видел этот вариант использования (но я вижу это), просто документируйте, что вы пытаетесь сделать, и, что более важно, , почему .

1 голос
/ 15 июля 2011

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

...