Как получить указатель на shared_ptr?

Я теперь взламываю старый код 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;
}

Я могу сделать это как это?

5
задан Georg Fritzsche 3 March 2010 в 14:34
поделиться

6 ответов

Нет.

По сути, вы должны сделать это по-старому, а затем каким-то образом преобразовать результат в 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 обычным способом.

2
ответ дан 13 December 2019 в 05:34
поделиться

Использование 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);
}

Обертывание устаревшей структуры / функций C в класс

В качестве альтернативы (как предложил 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 можно было копировать, убедитесь, что реализованы конструктор копирования и оператор присваивания, чтобы выполнялось глубокое копирование.

8
ответ дан 13 December 2019 в 05:34
поделиться

Вы всегда можете сделать это «по-старому», а затем назначить этот src указатель на shared_ptr с помощью reset () или make_shared () .

0
ответ дан 13 December 2019 в 05:34
поделиться

Я не думаю, что ваши вопросы имеют смысл. Если 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
}

Получение указателя внутри общего указателя и его изменение нарушит инварианты общего указателя: вы измените указатель, но не обновите счетчик общих ресурсов .

2
ответ дан 13 December 2019 в 05:34
поделиться

Я бы использовал этот код для решения вашей проблемы:

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: удаление ошибочной части моего ответа.

0
ответ дан 13 December 2019 в 05:34
поделиться

Вы также перерабатываете my_src_create()?

Учитывая название функции, я бы вернул boost::shared_ptr, а не передавал предварительно созданный, так как это гораздо понятнее и чище, ИМХО. Если только функция не возвращает какой-то код неудачи/успеха, но с этим лучше бороться, выбрасывая исключение.

Если вы отчаянно хотите передать пустой shared_ptr, вы можете передать его по неконстантной ссылке и использовать shared_ptr::reset() внутри my_src_create для присвоения ему нового значения.

0
ответ дан 13 December 2019 в 05:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: