Это то, что возникло недавно и, как мне кажется, не должно работать так, как, по-видимому, работает:
#include <iostream>
#include <memory>
int main()
{
std::shared_ptr<int>& ptr = const_cast<std::shared_ptr<int>&>(
static_cast<const std::shared_ptr<int>&>(
std::shared_ptr<int>(
new int(5), [](int* p) {std::cout << "Deleting!"; *p = 999; delete(p); }
)
)
);
std::cout << "I'm using a non-const ref to a temp! " << *ptr << " ";
}
Использование shared_ptr
здесь не обязательно, но настраиваемое средство удаления позволяет легко продемонстрировать время жизни полученного объекта. Итоговый результат Visual Studio, Clang и GCC одинаков:
Я использую неконстантную ссылку на темп! 5 Удаление!
Это означает, что время жизни результирующего shared_ptr
с помощью некоторого механизма было увеличено до соответствия сроку жизни std::shared_ptr<int>& ptr
.
Что творится?
Теперь я знаю, что время жизни временного будет увеличено до времени жизни ссылки в случае постоянной ссылки. Но единственный именованный объект - это неконстантная ссылка, все остальные промежуточные представления, как я ожидал, будут иметь время жизни, равное только выражению инициализации.
Кроме того, у Microsoft есть расширение, которое позволяет неконстантным ссылкам продлевать время существования привязанного временного объекта, но такое поведение, по-видимому, присутствует, даже когда это расширение отключено, и, кроме того, также появляется в Clang и GCC.
Согласно этому ответу, я считаю, что временный объект неявно создается как const
, поэтому попытка изменить объект, на который ссылается ptr
, вероятно, undefined, но я не уверен, что эти знания что-то говорят мне о том, почему продлевается время жизни. Насколько я понимаю, это акт изменения константы, которая является UB, а не просто взятие на нее неконстантной ссылки.
Я понимаю, что должно происходить следующим образом:
Type()
создает prvalue без спецификации cv.static_cast<const Type&>(...)
материализует это prvalue в const xvalue со временем жизни, равным внутреннему выражению. Затем мы создаем ссылку const lvalue на это const xvalue. Время жизни xvalue увеличивается, чтобы соответствовать времени жизни ссылки const lvalue.const_cast<Type&>(...)
создает ссылку lvalue, которая затем присваиваетсяptr
. Срок действия ссылки на const lvalue истекает, а вместе с ним и материализованное значение x.Я пытаюсь прочитать висящую ссылку
ptr
, и случаются неприятности.
Что не так в моем понимании? Почему не выделены курсивом фрагменты?
В качестве дополнительного бонусного вопроса: правильно ли я считаю, что базовый объект является константным, и что любая попытка изменить его с помощью этого пути приведет к неопределенному поведению?
const
, но я действительно понятия не имею, что на самом деле происходит - person 463035818_is_not_a_number   schedule 04.12.2019const_cast
(6.6.1) применяется кstatic_cast
(6.6.2), который запускает временную материализацию (6.1) - person Language Lawyer   schedule 04.12.2019