Обеспечить безопасное использование класса, содержащего ссылку или необработанный указатель

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

class DoStuffWithRef
{
DoStuffWithRef(LargeObject& lo) : lo_(lo) {}

// a bunch of member functions, some of them useful
// [...]

private:
LargeObject& lo_;
};

Класс разработан таким образом, что единственное разумное использование — это когда по крайней мере одна другая сущность владеет объектом, который lo_ Рекомендации. Если клиентский код использует класс соответствующим образом, нет необходимости DoStuffWithRef иметь право собственности на LargeObject,

Есть ли способ применить это использование или сообщить об ошибке, если класс используется не по назначению? Можно ли что-нибудь сделать, кроме документирования предполагаемого использования DoStuffWithRef?

Например, автоматически сохраненный DoStuffWithRef может относиться к автоматически сохраненному LargeObject,

void foo()
{
LargeObject lo;
DoStuffWithRef dswr(lo);
// some code that makes use of the DoStuffWithRef instance
return;
}

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

Проблема в том, что для клиентского кода очень возможно создать DoStuffWithRef экземпляр, который в конечном итоге с висящей ссылкой. Если никто не имеет права собственности на LargeObject упоминается DoStuffWithRefтогда наступает хаос, когда DoStuffWithRef пытается получить доступ к LargeObject, Хуже того, хаос может наступить только спустя много времени после ошибки.

Когда это всплыло в прошлом, я использовал boost::shared_ptr<> вместо ссылки (это было в C ++ 03). Это не совсем правильно выражает семантику класса. Предпосылка в том, что DoStuffWithRef не требует владения — он предназначен для работы с объектами, принадлежащими другим, и если никто не владеет объектом, то функциональность, предоставляемая DoStuffWithRef не имеет смысла. Передача прав собственности DoStuffWithRef имеет ненужные накладные расходы и вынуждает семантику совместного владения. weak_ptr<> также будет иметь неверную семантику, потому что мы не должны спрашивать во время выполнения, если указатель действителен.

У меня никогда не было такого сценария в чувствительном к производительности разделе кода или в случае, когда совместное владение было значительным бременем, так что это просто не имело значения, но мне хотелось бы знать, как точно выразить это в C ++. Расходы небольшие, но они также не нужны. Что еще более важно, shared_ptr<> будет скрывать неправильное использование класса. Если DoStuffWithRef, модифицированный для использования shared_ptr<>является единственным оставшимся владельцем LargeObjectзатем в течение короткого периода времени оборванная ссылка была предотвращена, но код клиента оказался на неизведанной территории.

0

Решение

DoStuffWithRef в противном случае с состоянием? Если нет, то похоже, что это набор утилитарных функций. Ссылка на LargeObject также может быть передана в качестве аргумента каждой функции. Это также решает вопрос о собственности.

В противном случае, если это состояние с сохранением состояния, это явный случай совместного владения, поскольку DoStuffWithRef действительно нужно продлить время жизни отдельного живого экземпляра LargeObject до самого себя. Или используйте слабый указатель и съешьте стоимость проверки во время выполнения …

0

Другие решения