Правильно ли говорить, что компилятор может заменить приведенное ниже выражение `a-> i` значением 1, потому что ...? - PullRequest
0 голосов
/ 19 мая 2018

Приведенный ниже код компилируется в GCC, clang и VS2017, а выражение a->i в операторе return заменяется его постоянным значением 1. Правильно ли говорить, что это допустимо, поскольку a равно не odr-используется в выражении a->i?.

struct A 
{ 
    static const int i = 1; 
}; 
int f() 
{ 
    A *a = nullptr; 
    return a->i;
}

PS: я считаю, a не odr-используется в выражении a->i, потому что этоудовлетворяет условию «если» в [basic.def.odr] / 4 следующим образом:

Переменная x, имя которой появляется в качестве потенциально вычисляемого выражения ex используется odr для ex , если , применяющее преобразование lvalue-to-rvalue (7.1) в x, не приводит к константному выражению (8.6), которое не вызывает никаких нетривиальных функций и,если x является объектом, ex является элементом набора потенциальных результатов выражения e, где преобразование lvalue-в-значение (7.1) применяется к e или eявляется выражением отброшенного значения (8.2).

В частности, выражение ex == aявляется элементом набора потенциальных результатов выражения e == a->i, в соответствии с [basic.def.odr] / 2 (2.3) , содержащим выражение ex, где lvalue-to-Преобразование в значение применяется к e.

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

i является static членом класса ... так как вы можете получить доступ к static членам класса, используя обычные методы для экземпляров, они не привязаны ни к какому конкретному экземпляру, поэтомувам не нужно разыменовывать указатель nullptr (как при использовании оператора sizeof).Вы также можете получить доступ к полю с помощью простого оператора

return A::i;

, поскольку вам не нужно создавать экземпляр для доступа к нему.Действительно, будучи const, компилятор позволяет управлять им как постоянным значением, поэтому только в том случае, если вам нужно использовать его адрес (с помощью оператора &), компилятор может обойти выделение его в постоянной памяти.

Следующий пример обнаружит, что:

#include <iostream>

struct A { 
    static const int i = 1; 
}; 

int main()
{
    std::cout << ((A*)0)->i << std::endl;
    std::cout << A::i << std::endl;
}

напечатает

$ a.out
1
1
$ _
0 голосов
/ 19 мая 2018

a используется в odr, потому что вы не можете выполнить первую часть операции «исключение»:

, применяя преобразование lvalue-to-rvalue (7.1) в x, дает постоянное выражение(8.6), который не вызывает никаких нетривиальных функций

Применение преобразования lvalue-to-rvalue в a не дает постоянного выражения.

Остальное - ядропроблемы 315 и 232 .


Ваш анализ разбивается двумя дополнительными способами:

  • "Выражение объекта" являетсяопределяется с помощью . формы доступа члена класса , поэтому вам нужно переписать a->i в точечную форму, т. е. (*a).i, перед применением [basic.def.odr] /2.3.a не является членом набора потенциальных результатов этого выражения.
  • Эта пуля сама по себе является дефектной, поскольку она написана с учетом нестатических элементов данных.Для статических элементов данных набор потенциальных результатов должен быть фактически именованным элементом статических данных - см. основной вопрос 2353 , поэтому a вдвойне не является членом набора потенциальных результатов этого выражения.

[expr.const] /2.7:

Выражение e является основным константным выражением , если только оценка e, следуя правилам абстрактной машины, будет вычислять одно из следующих выражений:

  • [...]
  • преобразование lvalue-в-значение, если оно не применяетсяв
    • энергонезависимое glvalue целочисленного или перечислимого типа, которое ссылается на полный энергонезависимый const-объект с предшествующей инициализацией, инициализированный постоянным выражением, или
    • энергонезависимое glvalueкоторый относится к подобъекту строкового литерала, или
    • - к энергонезависимому объекту glvalue, который относится к энергонезависимому объекту, определенному с помощью constexpr, или который относится к неизменяемому подобъекту такого объектаили
    • энергонезависимое glvalue литерального типа, которое относится к энергонезависимому объекту, время жизни которого началось в пределах оценки e;
  • [...]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...