1

我有代码 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数组在哪里?(在静态内存、自动内存或无存储位置)?

4

2 回答 2

4

在正常功能中,它将是临时的,存储在自动存储器中。由于n是一个编译时间常数,它可以被优化为简单地返回值,删除数组。

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

于 2013-09-05T12:14:46.870 回答
2

由于n在函数中不能是变量,例如

size_t n;
std::cin >> n;

std::cout << mask<n>() << std::endl;

将无法编译,因为n在编译时不是常量,编译器根本不需要存储数组。一般来说,一个constexpr函数不应该生成任何“代码”,而不是某种常量值。

我的编译器似乎不接受此处发布的代码 - 可能是因为它现在有点古老(它是 gcc 4.6.3 - 我也尝试过 clang++,但它失败了,因为它尝试使用 4.6.3 标头,这显然不是' t 在“铿锵味”中)。

当然,这样写要容易得多:

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;
}
于 2013-09-05T12:25:08.237 回答