немогу сообразить как правильно построить работу функции чтобы учесть следующие факты: 1. переложить контроль за удаление динамически созданных объектов на умные указатели. 2. не терять память в случае исключения 3. правильно обрабатывать отсутствие резульата вот код функции, для выборки из БД некоторых данных (одно строки) превращения и в объект моего класса и возврат пользователю Code: /// получить PersonInfo по ID (ptrPersonInfo) BussinesObject::ptrPersonInfo PersonDB::GetPersonInfoOnID(const int id) throw(sql::SQLException) { boost::shared_ptr<sql::Connection> con(Connect()); boost::shared_ptr<sql::PreparedStatement> prep_stmt( con->prepareStatement(QueryPersoneOnID)); prep_stmt->setInt(1, id); boost::shared_ptr<sql::ResultSet> res(prep_stmt->executeQuery()); PersonInfo* pers; if (res->next()) { pers = new PersonInfo(id, res->getString("first_name"), res->getString("last_name"), res->getString("birthday")); } return ptrPersonInfo(pers); } где Code: typedef boost::shared_ptr<PersonInfo> ptrPersonInfo; typedef std::vector<ptrPersonInfo> vecPtrPersonInfo; typedef boost::shared_ptr<vecPtrPersonInfo> ptrVecPtrPersonInfo; тут наблюдаются следующие проблемы: 1. в случае если возникнет какоето исключение в этот момент Code: pers = new PersonInfo(id, res->getString("first_name"), res->getString("last_name"), res->getString("birthday")); память будет утеряна. Возможно решить за счет try catch, но что делать в catch ? возвращать пустой объект или передавать исключение выше по иерархии вызова ? 2. если выборка из БД будет пустой Code: if (res->next()) { то будет произведене попытка инициализации умного указателя указателем не на что Code: return ptrPersonInfo(pers); Возможно стоит в этом случае инициализировать shared_ptr пустым объектом, но както не красиво. как бы вы решили эти проблемы ?
Возвращай из функции auto_ptr. В конце концов, он ради этого изначально и был создан. PHP: ... std::auto_ptr<PersonInfo> pers; if (res->next()) { pers.reset(new PersonInfo(id, res->getString("first_name"), res->getString("last_name"), res->getString("birthday"))); } return pers; После вызова функции проверять, не нулевой ли указатель оттуда вернулся. Спецификация исключений не поддерживается компиляторами, только если не задано просто throw(), так что это можно убрать. В новом стандарте вроде бы от всего, кроме просто throw(), вообще отказались. А вообще, архитектура изначально неверна. Из функции нужно возвращать никакие не смартпоинтеры, а сам объект. Добавить в него конструктор без параметров и предусмотреть метод вроде is_empty(), который будет говорить, есть ли информация в этом объекте, так было бы лучше. Чем меньше new в программе, тем лучше. А уж от delete следует избавляться вообще.
чем там плох возврат смарт поинтера/просто указателя (просто указателя плох тем что мы перекладываем ответственность на пользователя). И чем так хорош возврат объекта ? Предположим есть некий объект. Есть функция как то формирующая этот объект и возвращающая его, а не указатель на него. Есть функция которая возвращает список таких объектов. Тогда в функции формирующей список, возможно захочется использовать функцию возвращающую один объект для формирования этого списка. Code: vector<Object> vec; vec.push_back(GetObject()); Тогда получается для того чтобы сформировать список, нужно вызвать конструктор копирования для каждого из создаваемых объектов... накладно. PS. я надеюсь ты мне щас опять мозг не взорвешь тем что и тут действует какая то оптимизация которая не копирует объект и использует тот же. Тогда придется сжечь 9/10 всех книг по С++
В случае возврата объекта копирование выполняться не будет, как я уже пояснял, а вот в случае возврата списка объектов без него уже не обойтись. В твоем примере списков нет, поэтому я и посоветовал возвращать объект, чтобы не следить вообще ни за чем. Вообще, можно и список возвращать с минимальными копированиями. Тип list, например, будет вызывать копирование объектов только при помещении их в него.