Сначала вы создаете объект a
типа const std::shared_ptr<const A> a
и инициализируете его указателем на некоторый тип B
. Это работает, только если вы можете присвоить B*
для A*
, поэтому должны быть такие отношения, как наследование. Игнорируя это, вы преобразуете объект одного типа в ссылку на другой тип с помощью reinterpret_cast:
Выражение glvalue типа T1 может быть приведено к типу «ссылка на T2», если выражение типа«Указатель на T1» может быть явно преобразован в тип «Указатель на T2» с помощью reinterpret_cast. Результат ссылается на тот же объект, что и у источника glvalue, но с указанным типом. [Примечание: то есть для l-значений эталонное приведение reinterpret_cast (x) имеет тот же эффект, что и преобразование * reinterpret_cast (& x) со встроенными операторами & и * (и аналогично для reinterpret_cast (x)). - конец примечания]
Для указателей reinterpret_cast сводится к преобразованию в void*
, а затем к целевому типу:
Указатель объекта может быть явно преобразован вуказатель объекта другого типа. 72 Когда значение v указателя типа объекта преобразуется в указатель объекта типа «указатель на cv T», в результате получается static_cast<cv T*>(static_cast<cv void*>(v))
.
Семантикадва статических приведения определены как:
Значение типа «указатель на пустоту cv1» может быть преобразовано в значение типа «указатель на cv2 T», где T - это тип объекта, а cv2 - этота же квалификация cv, что и cv1 или более высокая, чем cv1. Значение нулевого указателя преобразуется в значение нулевого указателя типа назначения. Если исходное значение указателя представляет адрес A байта в памяти, и A удовлетворяет требованию выравнивания T, то результирующее значение указателя представляет тот же адрес, что и исходное значение указателя, то есть A. Результат любого другого такого указателяпреобразование не указано.
Платформа, на которой я работаю, имеет ближний и дальний указатели, которые являются 16 или 32-битными. В этом случае типы shared_ptr<A>
и shared_ptr<B>
имеют разный размер и выравнивание, и приведение одного к другому является неопределенным поведением. Если выравнивание совпадает, результат статического приведения определен.
Однако, первое предложение о reinterpret_cast для ссылки также содержит примечание
[ Note: That is, for lvalues, a reference
cast reinterpret_cast<T&>(x) has the same effect as the conversion *reinterpret_cast<T*>(&x) with
the built-in & and * operators (and similarly for reinterpret_cast<T&&>(x)). —end note ]
, поэтому в основномприведение семантически идентично преобразованию указателя с немедленной разыменовкой. Даже если указатели имеют одинаковый размер (и совместимое выравнивание), использование приведенного указателя нарушит строгое правило псевдонима, поскольку разыменование является доступом.
Если программа пытается получить доступ к сохраненному значениюДля объекта через glvalue, отличного от одного из следующих типов, поведение не определено: 53 - динамический тип объекта, - cv-квалифицированная версия динамического типа объекта, - аналогичный тип (как определено в 4.4)к динамическому типу объекта, - тип, который является типом со знаком или без знака, соответствующим динамическому типу объекта, - тип, который является типом со знаком или без знака, соответствующим cv-квалифицированной версии динамического типа объектаобъект, - агрегатный или объединенный тип, который включает один из вышеупомянутых типов среди своих элементов или нестатических элементов данных (включая, рекурсивно, элемент или нестатический элемент данных субагрегата или автономного объединения),