我有代码C ++ 11:
template<std::size_t n>
static inline constexpr uint32_t mask() noexcept
{
static_assert(n <= 32, "!");
using list = uint32_t[];
return list{
0x0u,
0x1u, 0x3u, 0x7, 0xfu, 0x1fu, 0x3fu, 0x7fu, 0xffu,
0x1ffu, 0x3ffu, 0x7ffu, 0xfffu, 0x1fffu, 0x3fffu, 0x7fffu, 0xffffu,
0x1ffffu, 0x3ffffu, 0x7ffffu, 0xfffffu, 0x1fffffu, 0x3fffffu, 0x7fffffu, 0xffffffu,
0x1ffffffu, 0x3ffffffu, 0x7ffffffu, 0xfffffffu, 0x1fffffffu, 0x3fffffffu, 0x7fffffffu, 0xffffffffu
} [ n ];
}
问:存储list
数组的位置在哪里? (在静态存储器中,自动存储器中,或者无处存储)?
答案 0 :(得分:4)
在正常功能中,它将是临时的,存储在自动存储器中。由于n
是编译时常量,因此可以优化它以简单地返回值,从而删除数组。
但是,这是constexpr
,因此应在编译时计算返回值。该数组在运行时根本不应存在。
答案 1 :(得分:2)
由于函数中的n
不能是变量,例如
size_t n;
std::cin >> n;
std::cout << mask<n>() << std::endl;
将无法编译,因为n
在编译时不是常量,编译器根本不需要存储该数组。通常,constexpr
函数不应生成除某种常量值之外的任何“代码”。
我的编译器似乎不接受这里发布的代码 - 可能是因为它现在有点古老了(它是gcc 4.6.3 - 我也尝试过clang ++,但它失败了因为它试图使用4.6.3标题,显然不是“铿锵味”)。
当然,写这个更容易:
template<std::size_t n>
inline constexpr uint32_t mask() noexcept
{
static_assert(n <= 32, "!");
return (1u << n) -1;
}
为了应对n == 32的特殊情况(避免使用UB,尽管在大多数结构中,上面的内容可能是正确的):
template<>
inline constexpr uint32_t mask<32>() noexcept
{
return ~0;
}