2015-01-19 2 views
0

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

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

[Предложение для наименее умного указателя мира] (http://www.open-std.org/jtc1/sc22/wg21/docs /papers/2014/n4282.pdf), который будет включен в C++ 17. – user657267

ответ

0

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

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

+0

Это может быть объект функции, который использует элементы данных как «функциональные параметры». Это, возможно, имеет состояние, но, конечно, не будет иметь изменчивого состояния.Причиной использования объекта функции вместо функции может быть то, что мы хотим параметризовать ее, а затем использовать ее для создания других объектов функций. – Praxeolitic

+0

Хорошо. Для меня тот факт, что вы упоминаете функциональные объекты, на самом деле означает, что он должен быть общим указателем. Поскольку вы проходите вокруг захваченной ссылки, она по своей сути опасна. –

+0

Я имею в виду, особенно если вы начинаете составлять объекты функций и т. Д., Достаточно скоро вы будете использовать его в другом потоке и т. Д. Таким образом, это боль, если вы не строго владеете собственностью. :) –

Смежные вопросы