constexpr函数可以返回本地对象的指针吗?

时间:2018-05-22 12:06:23

标签: c++ c++14

constexpr函数定义为(c ++ 14)

  

constexpr函数必须满足以下要求:

     
      
  • 一定不能虚拟
  •   
  • 其返回类型必须为LiteralType,其每个参数必须为LiteralType
  •   
  • 存在至少一组参数值,使得函数的调用可以是a的评估子表达式   核心常量表达式(对于构造函数,在常量中使用)   初始化程序就足够了)(因为C ++ 14)。无需诊断   违反此项目。
  •   
     

函数体必须删除或默认或包含any   陈述除了:

     
      
  • asm声明
  •   
  • 一个转到声明
  •   
  • 带有除case和default之外的标签的声明
  •   
  • 试用块
  •   
  • 非文字类型变量的定义
  •   
  • 静态或线程存储持续时间变量的定义
  •   
  • 未执行初始化的变量的定义。
  •   

现在跟随func1符合要求并编译

constexpr int * func1 (int a)
{
  int b = 4;
  return &b;
}
int main()
{
    constexpr int * a = func1(3);
    int arr[*a];  
    std::cout << a << std::endl;
}

现在我的问题是func1是如何成为constexpr的。它在编译时如何知道局部变量的地址?

我正在使用gcc 6.4.0

3 个答案:

答案 0 :(得分:4)

  

现在我的问题是如何将func1变成constexpr。

你确定吗?

尝试询问编译时值,将其保存在constexpr变量中;通过例子

constexpr int * a = func1(3);

你应该得到一个错误/警告列表,如(来自我的clang ++ 3.8.1)

tmp_003-14,gcc,clang.cpp:7:11: warning: address of stack memory associated with
      local variable 'b' returned [-Wreturn-stack-address]
  return &b;
          ^
tmp_003-14,gcc,clang.cpp:11:21: error: constexpr variable 'a' must be
      initialized by a constant expression
    constexpr int * a = func1(3);
                    ^   ~~~~~~~~
tmp_003-14,gcc,clang.cpp:11:21: note: pointer to 'b' is not a constant
      expression
tmp_003-14,gcc,clang.cpp:6:7: note: declared here
  int b = 4;
      ^

嗯,实际上,从我的g ++ 6.3.0开始,我只得到一个警告

tmp_003-14,gcc,clang.cpp: In function ‘constexpr int* func1(int)’:
tmp_003-14,gcc,clang.cpp:7:7: warning: address of local variable ‘b’ returned [-Wreturn-local-addr]
   int b = 4;
       ^

答案 1 :(得分:4)

  

如何在编译时知道局部变量的地址?

它没有。

你的引言中的第三个子弹永远不会满足:

  

至少存在一组参数值,例如a   函数的调用可以是a的一个被评估的子表达式   核心常量表达式(对于构造函数,在常量中使用)   初始化程序就足够了)(因为C ++ 14)。 无需诊断   违反此项目的行为。

编译器不会抱怨它,因为它不是必需的,直到你通过尝试在需要正确的func1函数的东西中使用constexpr来进行抱怨,例如:

std::array<int, func(3)> d;

这不会编译,你的编译器会告诉你原因。

答案 2 :(得分:1)

在您的代码中,当func1()返回时,b超出了范围。
因此,与b之外的func1()相关的任何用法都是未定义的行为

constexpr int * func1 (int a)
{
  int b = 4; // remember: b is non-static
  return &b;
}

int * a = func1(3); // b is out of scope here

此外,来自expr.const

核心常量表达式满足:

  

(5.2)如果值是指针类型,则它包含一个地址   具有 static 存储持续时间的对象,地址超过结束时间   这样的对象,函数的地址或空指针值

在您的情况下,b不是static,这意味着func1() 常量表达式