Допустим, у меня есть класс изображения, который ссылается на буфер, содержащий огромное количество данных.
При вызове конструктора копирования было бы неплохо не копировать данные, если в этом нет крайней необходимости.
Однако, если я создаю новый объект изображения из существующего константного объекта, новый объект изображения начинается в неконстантном состоянии, что позволяет изменять данные изображения в новом объекте, даже если данные изображения в старом объект не мог.
Я полагаю, что это фундаментальная проблема в C++, потому что объект shared_ptr имеет ту же проблему: если вы получили константный shared_ptr, вам нужно только скопировать его в неконстантный объект shared_ptr (через конструктор), чтобы получить изменчивый объект, который кажется коварным способом противодействия константной правильности. Необработанные указатели не имеют этой проблемы, поскольку такая копия не разрешена.
Я понимаю, что члены-указатели по своей природе не наследуют константность от своего владельца, но то, что мне нужно, — это способ построить класс, чтобы он выглядел так, чтобы было легко гарантировать, что содержимое константного объекта остаются постоянными
Этот вопрос дает частичный ответ на этот вопрос, поскольку он предлагает использовать std::experimental::propagate_const
, чтобы убедиться, что указатель в константном объекте становится константным указателем:
Как сделать указатель с глубокой константой
Однако я считаю, что это не решает проблему того, как гарантировать, что конструктор копирования с константным объектом, явно указывающим на константные данные, становится объектом, который не может изменять указанные данные.
Если вы задумаетесь о существовании
iterator
иconst_iterator
и о том, какие из них можно построить из других, станет возможным один потенциальный подход. В любом случае вы не можете «гарантировать, что конструктор копирования с константным объектом, явно указывающим на константные данные, станет объектом, который не может изменить указанные данные». С++ так не работает на фундаментальном уровне.Вам не нужно копировать
const std::shared_ptr<…>
, чтобы получить непостоянный доступ к указанному объекту:*
уже сделает это. У указателей просто есть два (или более) места для размещенияconst
; это это позор, что система типов не позволяет нам автоматически преобразовывать интеллектуальные указатели всеми способами, которыми мы можем использовать необработанные указатели, но вы определенно можете написатьstd::const_pointer_cast<const …>(sp)
для обеспечения const черезstd::shared_ptr
, так что это может не соответствовать «фундаментальной проблеме».