为什么 constexpr 方法可以 return 正确 class 在执行过程中值发生变化的成员?

Why constexpr method can return correctly class members whose value change during execution?

我刚刚发现 constexpr 方法 可以 return 正确地 class 成员的值在执行期间更改 。我的问题是,如果 constexpr 方法应该在编译时完全评估,这怎么可能?

下面的示例正确输出 Value: 0,然后是 Value: 5。更重要的是,如果我将 a.change(5) 更改为编译器无法预测的内容(例如 a.change(atoi(argv[1]))a.change(rand() % 10 + 1) 它仍然有效。为什么?为什么它甚至可以编译?

#include <iostream>

class A
{
    public:
        void change(int value) { x = value; }
        int get() const { return x; }
        constexpr int value() const noexcept { return x; }
    private:
        int x{0};
};

int main()
{
    A a;

    std::cout << "Value: "  << a.get() << std::endl;
    a.change(5);
    std::cout << "Value: "  << a.get() << std::endl;
}

提前致谢

在您的示例中,您甚至没有调用 constexpr 函数,而是调用了 get,这不是 constexpr.

但是,constexpr 函数 可以 在编译时求值,但如果无法进行编译时求值,也可以在 运行 期间求值。

如果您调用 value 而不是 get,它仍然可以工作并且函数将在 运行 时被计算。

为了强制编译时求值,可以这样写

constexpr auto val = a.value();

如果无法进行编译时评估,这确实会给您一个错误。

constexpr 意味着您可以在核心常量表达式中使用该函数,只要您有 constexpr 个参数即可。它仍然可以在其他上下文中使用。

就目前而言,您不能在核心常量表达式中使用 A::value,因为您无法获得 constexpr A。如果你有

class A
{
    public:
        constexpr A() = default;
        constexpr void change(int value) { x = value; }
        constexpr int get() const noexcept { return x; }
    private:
        int x{1};
};

您可以编写一个在编译时修改 A 的函数。

constexpr int stuff(A a) {
    a.change(10);
    return a.get();
}

See it on coliru

constexpr 函数通常在编译时计算 仅当 它们接收 constexpr 参数时,对于它包含 this 指针的方法.

#include <iostream>

class A
{
    public:
        void change(int value) { x = value; }
        constexpr int value() const noexcept { return x; }
    private:
        int x{0};
};

int main()
{
    constexpr const A foo;
    const A bar;// Const it not enough.

    static_assert(foo.value()==0);
    static_assert(bar.value()==0);// ERROR:  non-constant condition for static assertion
}