【问题标题】:Can you use the address of a constexpr variable?您可以使用 constexpr 变量的地址吗?
【发布时间】:2020-06-22 12:42:23
【问题描述】:

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

在我提交的一个补丁中,我将该变量的声明更改为静态 constexpr。对此更改的一位审阅者有顾虑:他认为您是否总是可以使用 constexpr 的地址是有问题的。他建议我将其设为常量。在谷歌搜索后,我找不到太多关于 constexpr 变量的地址和对它的担忧。有人能解释一下关于 constexpr 变量地址的保证以及使用它的注意事项(如果有的话)吗?

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

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

谢谢!

【问题讨论】:

  • 所有constexpr 所做的只是通知编译器它能够在编译时评估函数或变量的。它不会改变ONE 在这种情况下是指一个左值,您当然可以获取它的地址。换句话说,它不会改变变量的生命周期,如果这是您(或您的同事)所关心的。

标签: c++ c++11 pointers constexpr memory-address


【解决方案1】:

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

如果对象具有非零大小

  • 不是潜在重叠的子对象,或者

  • 不属于类类型,或

  • 是具有虚成员函数或虚基类的类类型,或者

  • 具有非零大小的子对象或非零长度的位域。

否则,如果对象是没有非静态数据成员的标准布局类类型的基类子对象,则它的大小为零。否则,对象大小为零的情况由实现定义。 除非是位域,否则大小非零的对象应占用一个或多个字节的存储空间,包括被其任何子对象全部或部分占用的每个字节。普通可复制或标准布局类型 ([basic.types]) 的对象应占用连续的存储字节。

强调我的

由于ONE是一个non-class-non-bit-field类型,它在存储中,你可以取它的地址。

【讨论】:

  • 位域是一个对象,占用一个存储区域,但没有地址。参见 [intro.object]/8。
  • @aschepler 好点。我已经更新了报价,因为它的效果更好。
  • 糟糕,我的意思是 C++17 [intro.object]/8,这是当今 LaTeX 源代码中的第 9 段。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2019-09-06
    • 1970-01-01
    • 2015-01-06
    • 1970-01-01
    • 2012-11-13
    • 2013-09-27
    • 2018-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多