Я прочитал эту статью , которая предполагает, что это может быть рискованно, и что умный указатель std::unique_ptr
может быть лучше, но эту проблему лучше всего решить с помощью современного C ++ 11 хода. семантика.
С этой точки зрения статья совершенно неправильная. Интеллектуальный указатель не устраняет «риск».
Краткий обзор соответствующих частей статьи
- Если класс возвращает ссылку
const
на элемент данных, клиентский код может вводить const_cast
и, таким образом, изменять элемент данных, не проходя через API класса. - В статье предлагается (неправильно) , что вышеупомянутого можно избежать с помощью умного указателя. Настройка заключается в том, чтобы класс поддерживал общий указатель на данные и чтобы получатель возвращал этот указатель на приведенный общий указатель на
const
данные.
Критика точек
Прежде всего, это не работает. Все, что нужно сделать, это отменить ссылку на интеллектуальный указатель, чтобы получить const
ссылку на данные, которая может быть тогда const_cast
, как и раньше. Используя собственный пример автора, вместо
std::string &evil = const_cast<std::string&>(obj.someStr());
используйте
std::string &evil = const_cast<std::string&>(*obj.str_ptr());
, чтобы получить те же результаты изменения данных при возврате интеллектуального указателя. Вся статья не ошибается, но она получает несколько неправильных пунктов. Это один из них.
Во-вторых, это не ваша забота. Когда вы возвращаете ссылку const
, вы сообщаете клиентскому коду, что это значение не должно изменяться. Если клиентский код делает так или иначе, это клиентский код нарушил соглашение. По сути, клиентский код вызывал неопределенное поведение, поэтому ваш класс может делать что угодно, даже взломать sh программу.
Каков современный лучший метод для этого?
Просто верните const
ссылку. (Большинство правил имеют исключения, но, по моему опыту, это правило выполняется в 95-99,9% случаев.)