как использовать reset с общим указателем const на неконстантный объект?

Я пытаюсь сбросить общий указатель, который является членом структуры, поступающей из итератора контейнера с постоянными структурами «элементами».
код не компилируется с ошибкой:

cannot convert 'this' pointer from 'const boost::shared_ptr<boost::log::v2s_mt_nt6::sinks::text_file_backend>' to 'boost::shared_ptr<boost::log::v2s_mt_nt6::sinks::text_file_backend> &'

эта ошибка говорит мне, что общий указатель const не может использоваться при сбросе??!! это правда?
если да, то как я могу преобразовать этот константный общий указатель в неконстантный, который будет использоваться при сбросе??


person ahmed allam    schedule 06.01.2020    source источник


Ответы (2)


Не пытайтесь сделать что-либо, что может удалить указатель, удерживаемый const shared_ptr<T>, например, вызов reset() на нем!

Если вы сделаете что-то вроде delete myConstSharedPtr.get();, delete будет снова вызываться для сохраненного указателя, когда счетчик ссылок достигнет 0, в основном вызывая двойную бесплатную ошибку.

Кроме того, вы должны пересмотреть свой дизайн и решить, действительно ли вы хотите использовать shared_ptr.


В конечном счете, в крайнем случае, если константа этого shared_ptr исходит из внешней библиотеки, которая не должна накладывать это const ограничение и которую вы не можете должным образом исправить, тогда const_cast создана для такой ситуации. Но забудьте об этом, вы не хотите использовать это, на самом деле.

Все еще там ? Вот как использовать const_cast для принудительного сброса const shared_ptr.

template<typename T>
void forceReset(const std::shared_ptr<T> ptr){
   const_cast<std::shared_ptr<T>&>(ptr).reset();
}

ПРЕДУПРЕЖДЕНИЕ: Если этот код на первый взгляд делает то, что вам нужно, это означает, что плохая библиотека, от которой вы зависите, дает утечку памяти. Действительно, невозможно отсоединить shared_ptr, то есть уничтожить его без обновления счетчика ссылок. Это означает, что если один из общих указателей, ссылающихся на принудительно удаленный ресурс, не будет динамически выделен и никогда не будет удален до конца программы, произойдет двойное освобождение, что приведет к неопределенному поведению... вероятно, к неприятному сбою.

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

template<typename T>
void forceReset(const std::shared_ptr<T> ptr){
   //This leaked shared_ptr will prevent automatic deletion
   new std::shared_ptr<T>(ptr);
   const_cast<std::shared_ptr<T>&>(ptr).reset();
}

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

person Meatboy 106    schedule 07.01.2020
comment
+1 В конечном счете, в крайнем случае, если константа этого shared_ptr исходит из внешней библиотеки, на которую вы не должны накладывать это ограничение на константу и которую вы не можете правильно исправить ..... это моя ситуация - person ahmed allam; 07.01.2020
comment
Если это ответ на ваш вопрос, не могли бы вы принять его? - person Meatboy 106; 07.01.2020
comment
вы не сказали мне, как использовать const_cast для изменения const shared_ptr??? я думаю, что const_cast не работает... - person ahmed allam; 07.01.2020

Если у вас есть const shared_ptr<T>, вы не можете изменить то, на что он указывает. Такова природа const. Таким образом, вы не можете вызвать reset, потому что это изменит то, на что он указывает.

Вы можете создать копию, отличную от const, и изменить то, на что она указывает, но это все равно не изменит исходный указатель const.

person Anthony Williams    schedule 06.01.2020
comment
Вы можете изменить содержимое переменной, на которую указывает const shared_ptr<T>, но вы не можете изменить значение удерживаемого ею указателя. Первое предложение двусмысленно, не могли бы вы пояснить, пожалуйста? Кроме того, выполнение неконстантной local копии const shared_ptr<T> кажется мне бессмысленным, поскольку это только влечет за собой накладные расходы, не принося никакой пользы. - person Meatboy 106; 07.01.2020