有点担心constexpr功能

时间:2017-08-10 09:14:45

标签: c++ c++11

请考虑以下代码:

constexpr const int* address(const int& r)
{
   return &r;
}


int main()
{
   int x = 10;
   constexpr const int* p = address(x); //error

   _getch();
   return 0;
}

这是一个错误:"函数调用必须在常量表达式中具有常量值"。确定。

两个问题:

  1. 如果' x'声明静态,没有错误。为什么呢?

  2. 如何在编译过程中获取变量地址? Aren他们是否在运行时分配?

5 个答案:

答案 0 :(得分:11)

  

如果'x'被声明为静态,则没有错误。为什么呢?

这是因为程序中总有一个x。它有一个地址(在正常条件下.data段中的某个位置)。

令人困惑的是,staticextern关键字都将存储持续时间指定为静态(它们在链接方面有所不同)

  

如何在编译过程中获取变量地址?它们不是在运行时分配的吗?

在运行时分配具有自动,动态或线程storage durations的变量。静态持续时间变量由编译器分配。 (链接器和操作系统可以更改位置,但是他们知道如何修复所有引用)

答案 1 :(得分:6)

指向static存储时间的变量的指针 a constexpr。您可以在以下程序中看到:

int main() {
    static int x;
    int y;
    constexpr int* px = &x; // Compilation is successful
    constexpr int* py = &y; // Compilation will fail
}

请参阅https://ideone.com/lc9u3E

px地址常量表达式。这是一个标准参考:

[5.19p3]:

  

地址常量表达式是prvalue核心常量表达式   指针类型的计算结果为具有静态的对象的地址   存储持续时间,函数地址或空指针   值,或类型为std :: nullptr_t的prvalue核心常量表达式。

答案 2 :(得分:2)

具有静态存储持续时间的变量的地址在编译时是未知的。 它仅在链接时才知道。 可以在编译时使用指向具有静态存储持续时间的变量的指针,因为地址的确切值无关紧要 - 在编译时不允许指针比较和强制转换。

答案 3 :(得分:0)

因为具有静态存储持续时间(全局或本地静态)的变量的地址在编译时是已知的,并且在程序执行期间不会更改。此外,整个过程中只有一个对象。

对于局部变量,上面所述的内容都没有。它被分配在堆栈帧中,其地址不同。同时也可以有几个这样的帧。

答案 4 :(得分:0)

问题2: “在编译过程中如何获得变量地址?它们不是在运行时分配的吗?”

x放在堆栈上,当堆栈发生变化时,它有不同的地址。如果x未在main()中声明,而在某些其他函数(从不同位置调用)中,则可能会发生这种情况。例如,尝试

#include <iostream>
constexpr const int* address(const int& r)
{
   return &r;
}


int f()
{
   int x = 10;

   const int* p = address(x);
   std::cout << "p=" << p << std::endl;
}

int g()
{
    int data[1000];
    f();
}

main()
{
   f();
   g();
   return 0;
}