【问题标题】:Behavior of a constexpr variable inside a function函数内 constexpr 变量的行为
【发布时间】:2015-07-28 20:48:06
【问题描述】:

我想知道当我在函数中定义一个 constexpr 变量时,内部会发生什么。程序是否存储了被调用函数的 constexpr 变量的每个版本?

例子:

template <class T, std::size_t M, std::size_t N>
template <std::size_t M2, std::size_t N2>
Matrix<T, M, N>::Matrix(const Matrix<T, M2, N2>& m)
{
    constexpr T m_min(MATHS::min(M, M2));
    constexpr T n_min(MATHS::min(N, N2));
    std::size_t i(0), j(0);
    for ( ; i < m_min ; ++i )
    {
        for ( j = 0 ; j < n_min ; ++j )
            m_elts[i][j] = m.m_elts[i][j];
        for ( ; j < N ; ++j )
            m_elts[i][j] = MATHS::CST<T>::ZERO;
    }
    for ( ; i < M ; ++i )
    {
        for ( j = 0 ; j < N ; ++j )
            m_elts[i][j] = MATHS::CST<T>::ZERO;
    }
}

//m_elts is : std::array<std::array<T, N>, M> m_elts;

【问题讨论】:

  • 视情况而定。可能需要为每个 constexpr 对象创建唯一地址。在某些时候甚至可以定义一个带有可变数据成员的 constexpr 结构,但我认为有一个针对此类事物的缺陷报告。
  • 提供具体的代码示例以获得更好的答案。正如@dyp 所说,这取决于 constexpr 变量的定义和使用方式。
  • 很好的跟进,我希望我有一个很好的答案给你。
  • 这个问题:Understanding the example on lvalue-to-rvalue conversion 是一个极端的例子,但给出了一个很好的例子,结果有点出乎意料。
  • 我撤回了我的近距离投票,因为这个例子让问题很清楚,尽管我仍然认为 MCVE 会更好。

标签: c++ c++11 constexpr


【解决方案1】:

这将取决于优化器和示例,但总的来说,我会说如果变量不是 ODR-used(松散地要么采用变量地址,要么绑定到引用) 那么编译器很可能不需要在运行时将值存储在某个地方。

鉴于以下人为设计的示例与您提供的示例大致相似:

#include <cstdio>
#include <algorithm>

template <typename T, size_t M, size_t N>
void func1( int x1, int x2, int x3 )
{
  constexpr T y1 = std::min(M,N) ;
  int y2 = x2 ;
  int z1 = x1 + y1 ;
  int z2 = x3 + y2 ;

  printf( "%d %d %d\n", x1, z1, z2 ) ;
}

template <typename T, size_t M, size_t N>
void func2( int x1, int x2, int x3 )
{
  constexpr int y1 = std::min(M,N) ;
  int y2 = x2 ;
  int z1 = x1 + y1 ;
  int z2 = x3 + y2 ;

  const int *p1 = &y1 ;

  printf( "%d %d %d %p\n", x1, z1, z2, p1 ) ;
}

int main()
{
  int x = 1, y = 2, z = 3 ;
  func1<int,10,20>( x, y, z ) ;
  func2<int,10,20>( x, y, z ) ;
}

我们可以看到使用godbolt live example,我们可以看到在func1 中,constexpr 变量y1 被替换为文字:

leal     10(%rdi), %edx #, z1

它不是 odr 使用的,因为我们不获取它的地址,也不绑定对它的引用,但在 func2 中,我们确实获取了它的地址并使用它,因此它需要在运行时存在:

movl    $10, 12(%rsp)   #, y1

【讨论】:

  • 好吧,我不知道 ODR 方面的事情。将静态辅助变量作为单位矩阵的简单引用指令可以从根本上改变程序的行为!
猜你喜欢
  • 2020-10-08
  • 1970-01-01
  • 2012-12-01
  • 2021-04-20
  • 1970-01-01
  • 1970-01-01
  • 2015-05-04
  • 2018-08-06
相关资源
最近更新 更多