Построить два объекта shared_ptr из одного и того же указателя
У меня есть проблема из "Стандартных расширений библиотеки C++":
Упражнение 6
В разделе 2.4.2 я сказал, что не следует создавать два объекта shared_ptr из одного и того же указателя. Опасность заключается в том, что оба объекта shared_ptr или их потомство в конечном итоге попытаются удалить ресурс, что обычно приводит к проблемам. На самом деле, вы можете сделать это, если вы осторожны. Это не особенно полезно, но напишите программу, которая создает два объекта shared_ptr из одного и того же указателя и удаляет ресурс только один раз.
ниже мой ответ:
template <typename T>
void nonsence(T*){}
struct SX {
int data;
SX(int i = 0) :
data(i) {
cout << "SX" << endl;
}
~SX() {
cout << "~SX" << endl;
}
};
int main(int argc, char **argv) {
SX* psx=new SX;
shared_ptr<SX> sp1(psx),sp2(psx,nonsence<SX>);
cout<<sp1.use_count()<<endl;
return 0;
}
но я не думаю, что это хорошее решение - потому что я не хочу решать его с помощью конструктора использования. кто-нибудь может дать мне лучший? THX, прости мой плохой английский.
4 ответа
Я получил ответ "СТАНДАРТ" от boost doc: http://www.boost.org/doc/libs/1_38_0/libs/smart_ptr/sp_techniques.html
Все, что вам нужно сделать, это построить второй shared_ptr
от первой shared_ptr
,
shared_ptr<SX> sp1( new SX );
shared_ptr<SX> sp2( sp1 );
Созданный SX будет затем правильно удален, только когда все общие указатели на него будут уничтожены.
Трюк, который вы нашли, действителен, но бесполезен. Центральная особенность shared_ptr
это подсчет ссылок, который вы подрываете здесь. Удалитель (второй аргумент конструктора) предназначен для использования shared_ptr
с ресурсами, отличными от простых указателей. Вы можете использовать его с файлами, например:
typedef boost::shared_ptr FilePtr;
void FileClose( FILE* pf ) { if ( pf ) fclose( pf ); }
FilePtr pfile( fopen( "filename" ), FileClose );
То же самое с соединениями с базой данных, сокетами и т. Д. И т. Д. И RAII в целом.
Вы можете посмотреть, как boost решает проблему с помощью shared_from_this. Вот код