Const корректность функции-члена, возвращающая shared_ptr <>

если у меня есть класс

class foo {
   private:
      std::shared_ptr<char> m_data;
   public:
      std::shared_ptr<const char> GetData()
      { return m_data;}
} 

Я считаю, что std::shared_ptr< T > должен отбрасываться на std::shared_ptr< const T > и делиться одним и тем же объектом, но что такое константная корректность функции?

IE - это действительно?

std::shared_ptr<const char> GetData() const;

Ответы

Ответ 1

  • Изменяет ли функция внутреннее состояние объекта? Нет. *

  • Предоставляет ли функция доступ к модификации доступа вызывающего (или другого внешнего окружения) к внутреннему состоянию объекта? Нет.

Это означает, что безопасно отмечать его как const.

* Примечание: @Yakk правильно указал в комментариях, что для некоторого определения "внутреннего состояния" функция действительно модифицирует его, поскольку он увеличивает счетчик ссылок на char, принадлежащий общему указателю m_data. Вы должны сами решить, является ли это неконстантной операцией; строго по правилам языка, это не так (потому что он изменяет то, на что указывает shared_ptr, а не сам shared_ptr). Но поскольку вы сначала сохраняете shared_ptr, я предполагаю, что вы в порядке с разделяющим правом собственности, поэтому его нельзя рассматривать как модификацию.

Ответ 2

Вы должны быть очень осторожны с таким кодом. В состоянии, в котором находится ваш код в настоящий момент, все будет в безопасности, потому что вы только обертываете shared_ptr, и никто не может изменять содержимое, потому что они являются частными. Однако, если вы расширяете свой код, есть тонкая, но серьезная ошибка, которую трудно отладить: если вы добавляете функции, которые изменяют данные, на которые указывают теги shared_ptr, тогда код, которому уже принадлежит shared_ptr, на const char из вашей функции GetData() будут отображаться измененные данные, а не копия данных.

В С++ ключевое слово const действительно означает только для чтения и не является неизменным, как многие думают, когда они впервые узнают об этом. Способ сделать ваш код будущим - это использовать std::shared_ptr<char> как тип данных для вашего члена данных m_data. Если это не подходит для ваших требований к вашему коду, подумайте о том, чтобы просто вернуть полную копию своих данных при вызове функции GetData(). Реализация copy-on-write может потребоваться, если у вас есть плохие ограничения производительности, но если вы не уверены в этих штрафах за производительность, избегайте копирования на запись, потому что это сложно из-за вышеприведенных причин.