Я теперь взламываю старый код C, пытаюсь сделать его большим количеством C++ / стиль Повышения:
существует функция распределения ресурсов, похож:
my_src_type* src;
my_src_create(&src, ctx, topic, handle_src_event, NULL, NULL);
я пытаюсь перенести src shared_ptr:
shared_ptr<my_src_type> pSrc;
Я забыл упоминать сейчас. Я должен сделать это как цикл
std::map<string, shared_ptr<my_src_type> > dict;
my_src_type* raw_ptr;
BOOST_FOREACH(std::string topic, all_topics)
{
my_src_create(&raw_ptr, ctx, topic, handle_src_event, NULL, NULL);
boost::shared_ptr<my_src_type> pSrc(raw_ptr);
dict[topic] = pSrc;
}
Я могу сделать это как это?
Нет.
По сути, вы должны сделать это по-старому, а затем каким-то образом преобразовать результат в shared_pointer
.
Вы можете сделать это, просто инициализировав shared_pointer
my_src_type* pSrc;
my_src_create(&src, ctx, topic, handle_src_event, NULL, NULL);
shared_ptr<my_src_type> sp(pSrc);
, но будьте осторожны, это не удастся, если функция my_src_create
может вернуть уже существующий объект. Кроме того, если есть функция my_src_destroy
, она не будет вызываться.
ИМХО, самый чистый способ - обернуть вашу структуру в класс C ++:
class MySrc {
my_src_type* pSrc;
public:
MySrc(...) { my_src_create(&pSrc, ...); }
~MySrc() { my_src_destroy(&pSrc); }
private:
MySrc(const MySrc&);
void operator=(const MySrc&); // disallow copying
};
, а затем использовать общий указатель для MySrc
обычным способом.
shared_ptr
на ресурсах в стиле C С помощью boost :: shared_ptr
вы можете передать указатель функции на «удаление», которое будет вызываться автоматически, когда ссылка счетчик достигает нуля. Эта функция позволяет использовать shared_ptr для управления ресурсами, возвращаемыми устаревшими API-интерфейсами C.
Вы можете оставить прежнюю my_src_create
нетронутой и предоставить новую «фабричную» функцию, которая возвращает shared_ptr
:
void my_src_deleter(my_src_type* raw_ptr)
{
my_src_destroy(raw_ptr);
}
typedef boost::shared_ptr<my_src_type> my_src_shared_ptr;
my_src_shared_ptr create_my_src(...)
{
my_src_type* raw_ptr;
my_src_create(&raw_ptr, ctx, topic, handle_src_event, NULL, NULL);
return my_src_shared_ptr(raw_ptr, &my_src_deleter);
}
std::map<string, my_src_shared_ptr> dict;
BOOST_FOREACH(std::string topic, all_topics)
{
dict[topic] = create_my_src(ctx, topic, handle_src_event, NULL, NULL);
}
В качестве альтернативы (как предложил jpalecek) вы можете обернуть my_src
в класс. Создание и уничтожение устаревших объектов my_src
обрабатывается в конструкторе и деструкторе. Если вы собираетесь это сделать, подумайте, хотите ли вы, чтобы ваш класс MySrc
был копируемым. Если MySrc
является тяжелым или дорогостоящим в создании, вы, вероятно, захотите сделать его не копируемым и рассмотрите возможность использования shared_ptr
, если планируется совместное владение ] MySrc
:
class MySrc
{
public:
typedef boost::shared_ptr<MySrc> Ptr;
MySrc(...) { my_src_create(&src_, ...); }
~MySrc() { my_src_destroy(&src_); }
// Other member functions that uses my_src legacy functions
private:
my_src_type* src_;
// Make copy-constructor and assignment private to disallow copies
MySrc(const MySrc& rhs) {}
MySrc& operator=(const MySrc& rhs) {return *this;}
};
std::map<string, MySrc::Ptr> dict;
BOOST_FOREACH(std::string topic, all_topics)
{
dict[topic] = MySrc::Ptr(
new MySrc(ctx, topic, handle_src_event, NULL, NULL) );
}
Обратите внимание, что вы также можете использовать класс MySrc
для обертывания устаревших функций, которые работают с экземплярами my_src.
Если вы хотите, чтобы MySrc
можно было копировать, убедитесь, что реализованы конструктор копирования и оператор присваивания, чтобы выполнялось глубокое копирование.
Вы всегда можете сделать это «по-старому», а затем назначить этот src
указатель на shared_ptr с помощью reset () или make_shared () .
Я не думаю, что ваши вопросы имеют смысл. Если my_src_create
переделывается, то передайте ссылку на общий указатель или вместо этого верните общий указатель. Если вы не переделываете этот метод, вы действительно не сможете этого сделать. Я рекомендую использовать для создания необработанный указатель, а затем обернуть его в общий указатель:
shared_ptr<my_src_type> src;
{
my_src_type* raw_src;
my_src_create(&raw_src, ctx, topic, handle_src_event, NULL, NULL);
src.reset( raw_src ); // hand ownership to shared_ptr
}
Получение указателя внутри общего указателя и его изменение нарушит инварианты общего указателя: вы измените указатель, но не обновите счетчик общих ресурсов .
Я бы использовал этот код для решения вашей проблемы:
my_src_type* src;
my_src_create(&src, ctx, topic, handle_src_event, NULL, NULL);
boost::shared_ptr<my_src_type> pSrc(src);
С этого момента pSrc
будет управлять выделенной памятью, на которую указывает my_src_type* src
.
EDIT: удаление ошибочной части моего ответа.
Вы также перерабатываете my_src_create()
?
Учитывая название функции, я бы вернул boost::shared_ptr, а не передавал предварительно созданный, так как это гораздо понятнее и чище, ИМХО. Если только функция не возвращает какой-то код неудачи/успеха, но с этим лучше бороться, выбрасывая исключение.
Если вы отчаянно хотите передать пустой shared_ptr, вы можете передать его по неконстантной ссылке и использовать shared_ptr::reset()
внутри my_src_create
для присвоения ему нового значения.