在我看来,拥有一个“总是返回5的函数”破坏或稀释了“调用函数”的意义。必须有一个原因,或者需要这个功能,否则它就不会出现在c++ 11中。为什么会在那里?

// preprocessor.
#define MEANING_OF_LIFE 42

// constants:
const int MeaningOfLife = 42;

// constexpr-function:
constexpr int MeaningOfLife () { return 42; }

在我看来,如果我写一个函数,返回一个字面值,然后我进行代码检查,有人会告诉我,我应该声明一个常量值,而不是返回5。


当前回答

它可以实现一些新的优化。Const传统上是类型系统的提示,不能用于优化(例如,Const成员函数可以合法地const_cast并修改对象,因此Const不能用于优化)。

Constexpr表示表达式真的是常量,前提是函数的输入是const。考虑:

class MyInterface {
public:
    int GetNumber() const = 0;
};

如果这在其他模块中公开,编译器不能相信GetNumber()在每次调用时不会返回不同的值——甚至在两次调用之间没有非const调用的情况下也不会返回不同的值——因为const可能已经在实现中被丢弃了。(显然,任何这样做的程序员都应该被枪毙,但语言允许这样做,因此编译器必须遵守这些规则。)

添加constexpr:

class MyInterface {
public:
    constexpr int GetNumber() const = 0;
};

编译器现在可以应用优化,缓存GetNumber()的返回值,并消除对GetNumber()的额外调用,因为constexpr是一个更强的保证,返回值不会改变。

其他回答

另一个用途(尚未提及)是constexpr构造函数。这允许创建编译时常量,这些常量不必在运行时进行初始化。

const std::complex<double> meaning_of_imagination(0, 42); 

将其与用户定义的字面量配对,就可以完全支持字面的用户定义类。

3.14D + 42_i;

它在某些方面很有用

// constants:
const int MeaningOfLife = 42;

// constexpr-function:
constexpr int MeaningOfLife () { return 42; }

int some_arr[MeaningOfLife()];

将它与特质类或类似的类联系起来,它会变得非常有用。

何时使用constexpr:

只要有编译时间常数。

刚刚开始将一个项目切换到c++11,遇到了一个非常好的constexpr情况,它清理了执行相同操作的替代方法。这里的关键点是,只有当函数声明为constexpr时,才能将其放入数组大小声明中。在许多情况下,我可以看到这在我所从事的代码领域非常有用。

constexpr size_t GetMaxIPV4StringLength()
{
    return ( sizeof( "255.255.255.255" ) );
}

void SomeIPFunction()
{
    char szIPAddress[ GetMaxIPV4StringLength() ];
    SomeIPGetFunction( szIPAddress );
}

这里的许多回答似乎有些相反,或者把安静的部分大声说出来,把吵闹的部分小声说出来。关于constexpr你需要知道的一件关键的事情是:

// This guarantees only that the value of "MeaningOfLife" can not be changed
// from the value calculated on this line by "complex_initialization()"
// (unless you cast away the const of course, don't do that).
// Critically here, everything happens at *runtime*.
const int MeaningOfLife = complex_initialization(1234, 5678, "hello");
// This guarantees that "MeaningOfLife" is fully evaluated and "initialized"
// *at compile time*.  If that is not possible due to complex_initialization()
// not being evaluatable at compile time, the compiler is required to abort
// compilation of the program.
// Critically here, to put a fine point on it, everything happens at
// *compile time*, guaranteed.  There won't be a runtime call to
// complex_initialization() at all in the final program.
constexpr int MeaningOfLife = complex_initialization(1234, 5678, "hello");

注意,是左边的常量使保证有存在的理由。当然,这取决于你是否能确保右边的值在编译时被求出来,重要的是,仅仅声明一个函数constexpr本身并不能做到这一点。

因此,您的问题的答案是,当您需要或希望它的初始化(右边发生的所有事情)完全在编译时发生或中断构建时,您应该声明一个变量constexpr。