Принимает ли адрес оборванных ссылок UB? [Дубликат]

В классах C ++ есть функция ввода их имени в свою область действия ( [класс] / 2 ):

Имя класса также вставляется в объем самого класса; это известно как имя введенного класса . Для проверки доступа имя введенного класса рассматривается так, как если бы это было публичное имя участника.

. В приведенном фрагменте кода используется Это. В определенных контекстах Commitment::Commitment называет сам класс, а в других - c'tor. Только последний Commitment(, где вы открываете круглые скобки, начинается определение c'tor.

И это может выглядеть намного хуже:

struct foo {
    foo();
};

foo::foo::foo::foo() = default;

Который вы можете видеть действительный C ++ Live .

12
задан Luchian Grigore 6 February 2013 в 15:41
поделиться

3 ответа

Во-первых, очень интересный вопрос.

Я бы сказал, что это неопределенное поведение, предполагая, что «оборванная ссылка» означает, что «время жизни объекта« ссылка на объект »закончилось, и хранилище, которое занимал объект , имеет были повторно использованы или выпущены ». Я основываю свои рассуждения на следующих стандартных правилах:

3.8 §3:

Свойства, приписываемые объектам в рамках этого международного стандарта, применяются к данному объекту только в течение его жизни. [Примечание: В частности, до начала жизни объекта и после его окончания жизни существуют существенные ограничения на использование объекта, как описано ниже ...]

Все случаи «как описано ниже» относятся к

До того, как срок жизни объекта запустился, но после того, как хранилище, которое будет занимать объект, было выделено38, или после того, как срок жизни объекта закончился и до хранилище, которое занимаемый объект повторно используется или освобожден

1.3.24: неопределенное поведение

поведение, для которого настоящий международный стандарт не предъявляет требований [Примечание: неопределенное поведение можно ожидать, если в этом Международном стандарте отсутствует явное определение поведения или когда программа использует ошибочную конструкцию или ошибочные данные. ...]

Я применяю следующий цикл мыслей к приведенным выше цитатам:

  1. Если стандарт не описывает поведение для ситуации, Функция не указана.
  2. Стандарт описывает только поведение объектов в течение их жизни и несколько особых случаев вблизи начала и конца их жизни.
  3. Таким образом, использование ссылки danling каким-либо образом не имеет поведения, предписанного стандартом, поэтому поведение не определено.
4
ответ дан Angew 26 August 2018 в 14:55
поделиться

Что делает неправильное поведение недопустимого объекта (ссылка, указатель, что угодно) неопределенным: lvalue-to-rvalue conversion (§4.1):

Если объект, к которому относится ссылка glvalue не является объектом типа T и не является объектом типа, производного от T, или если объект не инициализирован, программа, которая требует этого преобразования, имеет неопределенное поведение.

Предполагая, что мы 't перегружен operator&, унарный оператор & принимает lvalue в качестве своего операнда, поэтому никакого преобразования не происходит. Наличие только идентификатора, как и в x;, также не требует преобразования. Вы получите только неопределенное поведение, когда ссылка используется как операнд в выражении, ожидающем, что этот операнд будет значением rvalue, что имеет место для большинства операторов. Дело в том, что выполнение &x фактически не требует доступа к значению x.

Я считаю, что ваш код хорошо определен.

Когда перегрузка operator& была перегружена, выражение &x преобразуется в вызов функции и не подчиняется правилам встроенных операторов - вместо этого он следует правилам вызова функции. Для функции &x вызов функции перевода означает либо x.operator&(), либо operator&(x). В первом случае преобразование lvalue-rvalue будет происходить на x, когда используется оператор доступа к члену класса. Во втором случае аргумент operator& будет инициализирован с помощью x (как в T arg = x), а поведение этого зависит от типа аргумента. Например, в случае, если аргумент является ссылкой lvalue, нет неопределенного поведения, поскольку преобразование lvalue-rvalue не происходит.

Итак, если operator& перегружен для типа x, код может быть или не быть корректным, в зависимости от вызова функции operator&.

Можно утверждать, что унарный оператор & полагается на наличие хотя бы некоторой допустимой области что у вас есть адрес:

В противном случае, если тип выражения равен T, результат имеет тип «указатель на T» и является значением praleue, которое является адрес выделенного объекта

И объект определяется как область хранения. После уничтожения объекта, эта область хранения больше не существует.

Я предпочитаю полагать, что это приведет только к неопределенному поведению, если к нему действительно обращается недопустимый объект. Ссылка все еще полагает, что это относится к некоторому объекту, и он может с радостью указать адрес, даже если он не существует. Однако это, кажется, некорректная часть стандарта.


Кроме

В качестве примера неопределенного поведения рассмотрим x + x. Теперь мы попали в другую нечеткую часть стандарта. Категория значений операндов + не указана. Как правило, из § 5/8 вытекает, что если он не указан, тогда он ожидает значение prvalue:

Всякий раз, когда выражение glvalue появляется как операнд оператора, который ожидает prvalue для этого операнда , для преобразования выражения в prvalue применяются переменные lvalue-to-rvalue (4.1), стандартные переменные (4.2) или стандартные функции (4.3).

Теперь, поскольку x является lvalue, требуется преобразование lvalue-rvalue, и мы получаем неопределенное поведение. Это имеет смысл, потому что добавление требует доступа к значению x, чтобы он мог выработать результат.

4
ответ дан Joseph Mansfield 26 August 2018 в 14:55
поделиться

Предположим, что x был инициализирован действительным объектом, который был затем уничтожен, применяется §3.8 / 6:

Аналогично, до того, как срок жизни объекта начался, но после хранения который будет занимать объект, был выделен или, по истечении срока жизни объекта и до хранения, которое объект занят повторно используется или выпущен, может использоваться любое значение gl, которое ссылается на исходный объект, но только ограниченным образом. По строительству или разрушению объекта см. 12.7. В противном случае такое значение glvalue относится к выделенному хранилищу (3.7.4.2), и использование свойств glvalue, которые не зависят от его значения, четко определено. Программа имеет неопределенное поведение, если:

- преобразование lvalue-to-rvalue (4.1) применяется к такому glvalue,

- glvalue используется для доступа к нестатическому член данных или вызов нестатической функции-члена объекта или

- glvalue привязан к ссылке на виртуальный базовый класс (8.5.3) или

- glvalue используется как операнд dynamic_cast (5.2.7) или как операнд typeid.

Итак, просто принимая адрес хорошо определен и (ссылаясь на соседний абзацы) даже можно продуктивно использовать для создания нового объекта вместо старого.

Что касается not , берущего адрес и просто записывающего x, это действительно делает абсолютно ничего, и это правильное подвыражение &x. Так что это тоже нормально.

3
ответ дан Potatoswatter 26 August 2018 в 14:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: