存储数组的地方,如果我在返回后声明它

Where stored array, if I declared it after return?

本文关键字:返回 声明 如果 数组 存储      更新时间:2023-10-16

我有代码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存储在哪里? (在静态内存中,自动内存中,还是无处存储)?

在正常函数中,它将是一个临时的,存储在自动内存中。由于n是一个编译时常量,因此可以优化它以简单地返回值,删除数组。

但是,这是constexpr的,因此应在编译时计算返回值。数组在运行时根本不应该存在。

由于函数中的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;
}