Можете ли вы использовать адрес переменной constexpr? - PullRequest
4 голосов
/ 10 марта 2020

У меня есть переменная, адрес которой передан в качестве четвертого параметра в setsocketopt . Обратите внимание, что этот параметр объявлен как постоянный указатель (const void *optval).

В патче, который я выставил на проверку, я изменил объявление этой переменной на stati c constexpr. У рецензента этого изменения были проблемы: он чувствовал, что было сомнительно, всегда ли вы можете взять адрес constexpr. Он предлагает мне сделать это const. Я не мог найти много об адресах переменных constexpr и проблемах с этим после поиска в Google. Может кто-нибудь объяснить, какие гарантии касаются адреса переменной constexpr и какие предостережения касаются его использования (если есть)?

В случае, если это полезно, вот код (я добавил static constexpr, это было просто int до):

static constexpr int ONE = 1;
setsockopt(socket_fd, IPPROTO_TCP, TCP_NODELAY, &ONE, sizeof(ONE));

Спасибо!

Ответы [ 2 ]

4 голосов
/ 10 марта 2020

Да, вы можете взять адрес любого объекта, который не является нетиповым параметром шаблона или типом битового поля. Переменная, объявленная constexpr (или переменная, которая неявно является константным выражением), может использоваться в большем количестве контекстов, а не в меньшем.

Это правда, что компилятор часто может избежать использования какого-либо хранилища для переменной constexpr если не нужно . Но если адрес будет взят, это, вероятно, потребует хранения памяти, поэтому компилятору нужно будет обрабатывать его как обычный объект в этом случае.

4 голосов
/ 10 марта 2020

Каждый объект гарантированно имеет адрес на [intro.object] / 8

Объект имеет ненулевой размер, если это

  • не является потенциально перекрывающимся подобъектом, или

  • не относится к типу класса , или

  • относится к типу классов с виртуальными функциями-членами или виртуальными базовыми классами, или

  • имеет подобъекты ненулевого размера или битовые поля ненулевой длины.

В противном случае, если объект является подобъектом базового класса с типом класса стандартной компоновки без нестандартных c членов данных, он имеет нулевой размер. В противном случае обстоятельства, при которых объект имеет нулевой размер, определяются реализацией. Если это не битовое поле, объект с ненулевым размером должен занимать один или несколько байтов памяти , включая каждый байт, который полностью или частично занят любым из его подобъектов. Объект типа тривиально копируемого или стандартного макета ([basi c .types]) должен занимать смежные байты хранилища.

выделение шахты

Поскольку ONE - это тип, не относящийся к классам и не битовые поля, он находится в хранилище, и вы можете взять его адрес.

...