2014-12-16 3 views
2

Я пытаюсь понять, как интеллектуальные указатели должны жить с помощью схемы владения объектами ROOT. Мне не нужно было ехать очень далеко. Посмотрите на этоВладение объектами CERN ROOT и C++ 11 Умные указатели

#include <iostream> 
#include <memory> 
#include "TH1F.h" 
#include "TFile.h" 

int main() 
{ 
    TFile f("out.root", "recreate"); 
    f.cd(); 
    std::unique_ptr<TH1F> h {new TH1F("h", "h", 100, -5, 5)}; 
    h->FillRandom("gaus", 10000); 
    h->Write(); 
    f.Close(); 

    return 0; 
} 

Гистограмма, которая обрабатывается уникальным указателем, принадлежала текущему gDirectory. Поскольку я вежливо закрыл файл перед тем, как выйти из моей программы, гистограмма была уничтожена парнем управления памятью ROOT. Теперь в конце main() мой указатель выходит из сферы действия, и его ресурс должен быть освобожден, но он уже освобожден!

Я не нашел ресурсов, связанных с тем, как предполагается, что владение объектами ROOT и управление памятью будут работать с интеллектуальными указателями C++ 11.

Мой вопрос к вам, вы используете интеллектуальные указатели в коде, где включено управление объектами ROOT? Используете ли вы умные указатели C++ 11 в эксперименте HENP?

+1

Если ROOT действительно заботится о собственности, почему вы хотите, чтобы это работало с уникальным_ptr? Я не думаю, что эта определенная часть ROOT предназначена для работы с интеллектуальными указателями (или смарт-что-либо.) – juanchopanza

+0

Ну, я хочу понять, каковы рекомендации различных экспериментаторов/пользователей по использованию интеллектуальных указателей в коде, который обрабатывает объекты ROOT , Если ожидается, что современный C++-код избавится от голых указателей, мы ожидаем увидеть более интеллектуальные указатели в кодах программистов. Так что мы должны просто запретить использование интеллектуальных указателей для обработки объектов ROOT? Отключить управление объектами ROOT? Другие планы от ROOT, чтобы обойти это? – Mustafa

+0

Уверен, но вам нужно использовать только интеллектуальные указатели, когда они вам понадобятся. Если что-то уже принадлежит динамически выделенному объекту, вы не можете пытаться взять на себя ответственность, если у владельца нет своего механизма выпуска. Также обратите внимание, что большая часть этого была, вероятно, «разработана» в дореволюционную эпоху. Один из подходов, который я видел, заключается в том, чтобы скрыть все это управление памятью за более современными интерфейсами, которые, похоже, не полагаются на глобальные объекты и странные соглашения. – juanchopanza

ответ

0

Ну, я думаю, чтобы сделать unique_ptr и ROOT счастливо женат, вы должны использовать пользовательский deleter.

В пользовательской Deleter вы должны проверить, если гистограмма все еще жив и удалить его, в противном случае не делать это независимо от колёсах

Что-то вроде (в псевдокоде)

auto deleter = [](TH1F* p) { key = FindKey(p->Name); if (key) delete p }; 

std::unique_ptr<TH1F, decltype(deleter)> h{new TH1F("h", "h", 100, -5, 5), deleter}; 

более сложные схемы могут быть разработаны .. .

+0

Кроме того, как вы узнали, если он был удален? – juanchopanza

+0

@juanchopanza IIRC (я имел дело с ROOT давно), вам нужно проверить ключ по имени, как я и предложил. Если ключ не является NULL, он находится в текущем контексте и может быть удален. –

+0

Вы можете проверить по имени, как это, но вы должны * знать * имя. Очевидно, что вызов 'p-> Name' не работает, если' p' уже удален. Если 'p' был удален, это просто segfaults. – Chris

2

Если вы используете TH1::AddDirectory(false), вы будете управлять гистограммами, а затем с помощью интеллектуальных указателей проблем не возникнет.

+0

Мой вопрос заключался в том, как сделать собственность объекта ROOT ** live ** с помощью интеллектуальных указателей. Не как отключить управление объектами ROOT. – Mustafa

1

Если вы используете std::unique_ptr, вы действительно хотите, чтобы он был единственным владельцем объекта. Вы можете отключить собственности Корневого объекта для одной гистограммы с h->SetDirectory:

#include <iostream> 
#include <memory> 
#include "TH1F.h" 
#include "TFile.h" 

int main() 
{ 
    TFile f("out.root", "recreate"); 
    f.cd(); 
    std::unique_ptr<TH1F> h {new TH1F("h", "h", 100, -5, 5)}; 
    h->SetDirectory(0); 
    h->FillRandom("gaus", 10000); 
    h->Write(); 
    f.Close(); 

    return 0; 
} 

Таким образом, вы по-прежнему иметь право собственности на объект суперпользователя для всех других гистограмм, но вы можете иметь это тот самостоятельно.