Благодаря использованию умных указателей или нет. Я хотел бы сделать для пользователя библиотеки явным, что все указатели, которые они передают в библиотеку, теперь должны принадлежать библиотеке (т. Е. Не освобождаться пользователем).
Многие библиотеки с открытым исходным кодом просто заявляют в своей документации, что библиотека владеет всем или нет. Они обсуждают ожидаемое время жизни передаваемых указателей. Конечно, существует более строгий способ донести эту информацию до пользователя.
Пример был бы великолепен.
Спасибо!
Используйте умный указатель владения во всех ваших классах, который вступит во владение (т.е. уничтожит объект, сделанный с ним), и любые указатели, переданные от пользователей, будут приняты этим умным указателем владения.
Хороший пример std::unique_ptr
, как только все будет сделано, уничтожит его объект.
Если вам нужно пользовательское уничтожение, вы можете передать его пользовательскому удалителю.
Еще лучше, конечно, иметь оба творения (т.е. через make_unique
) в ваших классах тоже, так как тогда у вас будет RAII, что позволит избежать всех утечек.
Если вы действительно этого хотите, вы должны предоставить в библиотеке методы для создания этих объектов вместо того, чтобы пользователи выделяли их. Не имеет смысла, что библиотека освобождает объект, который она не создала, поскольку она не может гарантировать, что они оба используют одно и то же средство выделения.
Существует возможность, что библиотека создает эти объекты, завернутые в специальный интеллектуальный указатель, который скрывает указатель и не позволяет внешнему клиенту освободить обернутые объекты, но всегда можно обойти охрану. По моему опыту, попытка быть слишком умным всегда приводит к обратным последствиям: все усложняется, но разработчик, использующий библиотеку, всегда может перехитрить его.
IMO, самый безопасный подход — это простой API управления жизненным циклом (например, CreateObject, DestroyObject) и четкая и краткая документация. Тогда пользователь волен выбирать, как управлять временем жизни (например, shared_ptr
/unique_ptr
с DestroyObject
как пользовательский удалитель, или что-то совсем другое).
Если вы пишете свои библиотечные функции, методы и конструкторы, чтобы взять std::unique_ptr<T>
по значению, тогда пользователь не сможет освободить указатель как unique_ptr
экземпляры будут очищены при перемещении копий аргументов.
class C;
void library_function(std::unique_ptr<C> by_value);
void user_code() {
std::unique_ptr<C> user_c{std::make_unique<C>("param", 5)};
library_function(user_c);
assert(user_c.get() == nullptr);
}
Если пользователь должен иметь возможность продолжать наблюдать за объектом, то вы можете принять shared_ptr
на интерфейсе, или вы можете предоставить методы-наблюдатели, которые возвращают необработанный (не принадлежащий) указатель или (лучше) ссылку.
Один из способов сделать это было бы перегрузить новый / удалить операторы, и использовать эти функции для фильтрации доступа. Например, new может создать объект, а затем сохранить адрес в некоторой частной статической структуре данных. Удаление может быть разработано так, чтобы оно блокировало любую попытку использования delete object
идиома, если не выполнены определенные условия.