const 与constexpr

const int i = 1;
constexpr int j = 1;

两者在大多数情况下是没有区别的。不过有一点是肯定的,就是如果i在全局名字空间中,编译器一定会为i产生数据。而对于j,如果不是有代码显式地使用了它的地址,编译器可以选择不为它生成数据

使用constexpr可以将一些计算在编译时完成,从而在运行时节省时间和资源。它可以用于以下几个方面:

  1. 编译时常量计算:通过将表达式标记为constexpr,编译器可以在编译时进行常量计算,并将结果直接嵌入到生成的代码中,避免了运行时的计算开销。
  2. 函数参数和返回类型推断:constexpr函数能够根据输入参数的常量性,推断出函数的返回值和其他变量的类型,从而优化编译过程。
  3. 在编译期执行复杂操作:C++11中要求函数体中只有一条语句,且该条语句必须是return语句。赋值的操作在常量表达式中也是不允许的。C++14对constexpr进行了扩展,使其能够执行更多的操作,例如循环和条件语句,从而在编译期执行复杂的逻辑,避免了运行时的开销。

#include <iostream>

constexpr int fibonacci(int n) {
    if (n <= 1) {
        return n;
    }
    else {
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
}

int main() {
    constexpr int n = 10;
    
    // 在编译时计算斐波那契数列的第n项
    constexpr int result = fibonacci(n);
    
    std::cout << "Fibonacci number at position " << n << ": " << result << std::endl;
    
    return 0;
}

在这个示例中,fibonacci函数被标记为constexpr,它在编译时计算斐波那契数列的第n项。由于n是一个编译时常量,在编译阶段就可以完成计算,而不需要在运行时进行递归调用。这样可以节省运行时的时间和资源。

通过constexpr函数推断返回类型

在这个示例中,sum函数使用constexpr和auto关键字,根据输入参数的常量性推断返回类型。这允许在编译期间进行类型检查和优化。

c++17引入constexpr if

#include <iostream>
#include <type_traits>

template<typename T>
void process(const T& value) {
    if constexpr (std::is_integral<T>::value) {
        std::cout << "Integral value: " << value << std::endl;
    }
    else if constexpr (std::is_floating_point<T>::value) {
        std::cout << "Floating-point value: " << value << std::endl;
    }
    else {
        std::cout << "Other value" << std::endl;
    }
}

int main() {
    int intValue = 5;
    float floatValue = 3.14;
    std::string stringValue = "Hello";

    process(intValue);      // 输出:Integral value: 5
    process(floatValue);    // 输出:Floating-point value: 3.14
    process(stringValue);   // 输出:Other value

    return 0;
}

在这个示例中,我们定义了一个process函数模板,它接受一个参数value。使用constexpr if语句,我们检查传入的参数的类型,并根据不同的类型执行不同的代码块。

在调用process函数时,根据传入的参数的类型,对应的if constexpr分支将会被选择,在编译时生成相应的代码。这样可以避免在运行时执行不必要的分支,提高代码的效率和性能。

需要注意的是,constexpr if中的条件表达式必须在编译时可求值,因此它通常与模板编程和类型特性结合使用。这样可以根据不同的类型或特性,在编译时生成不同的代码逻辑。