您可以使用 constexpr 变量的地址吗?

Can you use the address of a constexpr variable?

我有一个变量,其地址作为第四个参数传递给setsocketopt。请注意,此参数声明为常量指针 (const void *optval).

在我提交审核的补丁中,我将该变量的声明更改为 static constexpr。此更改的审阅者有顾虑:他认为您是否始终可以获取 constexpr 的地址值得怀疑。他建议我把它设为 const。在谷歌搜索后,我找不到太多关于 constexpr 变量的地址和关注点。有人可以解释关于 constexpr 变量地址的保证以及使用它的注意事项(如果有的话)吗?

如果有帮助,这里是代码(我添加了 static constexpr,之前只是一个 int):

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

谢谢!

保证每个对象都有一个地址 [intro.object]/8

An object has nonzero size if it

  • is not a potentially-overlapping subobject, or

  • is not of class type, or

  • is of a class type with virtual member functions or virtual base classes, or

  • has subobjects of nonzero size or bit-fields of nonzero length.

Otherwise, if the object is a base class subobject of a standard-layout class type with no non-static data members, it has zero size. Otherwise, the circumstances under which the object has zero size are implementation-defined. Unless it is a bit-field, an object with nonzero size shall occupy one or more bytes of storage, including every byte that is occupied in full or in part by any of its subobjects. An object of trivially copyable or standard-layout type ([basic.types]) shall occupy contiguous bytes of storage.

强调我的

由于 ONE 是非 class 非位域类型,它在存储中,您可以获取它的地址。

是的,您可以获取任何不是非类型非引用模板参数或位域的对象的地址。声明为 constexpr 的变量(或隐含为常量表达式的变量)可以在更多上下文中使用,而不是更少。

确实,如果不需要,编译器通常可以避免为 constexpr 变量使用任何内存存储。但是如果地址被占用,那可能需要内存存储,所以在这种情况下编译器需要更像普通对象一样对待它。