Как использовать сброс с константным общим указателем на не константный объект? - PullRequest
0 голосов
/ 06 января 2020

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

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 не разрешен для сброса ?? !! это правда?
если так, как я могу преобразовать этот общий указатель const в non const для использования при сбросе ??

Ответы [ 2 ]

4 голосов
/ 06 января 2020

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

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

1 голос
/ 07 января 2020

Не пытайтесь делать что-либо, что могло бы удалить удержание указателя с помощью 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();
}

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...