在C++中,何时使用const而不是constexpr变量

42 浏览
0 Comments

在C++中,何时使用const而不是constexpr变量

constexprconst 之间有什么区别?\n

    \n

  • 我什么时候只能使用其中一个?
  • \n

  • 我什么时候可以同时使用两者,并且应该如何选择?
  • \n

0
0 Comments

使用const关键字可以保证程序不会改变对象的值,但是const不能保证对象的初始化类型。使用constexpr关键字可以在一定条件下保证对象进行静态初始化,并且可以控制表达式的评估时间。constexpr关键字可以让我们定义真正的常量表达式,这对于时间关键的应用程序、系统编程、模板以及任何依赖于编译时常量的代码都非常重要。

在C++中,常量表达式函数是通过声明constexpr关键字来定义的。它的函数体必须是非虚函数,并且除了typedef和static assert之外,函数体只能包含一条return语句。常量表达式函数的参数和返回值必须具有字面类型。它可以与非常量表达式参数一起使用,但这样做的结果不是一个常量表达式。

常量表达式函数的目的是用来替代宏和硬编码的字面值,而不会影响性能或类型安全。

常量表达式对象是通过声明constexpr关键字来定义的对象。它必须用常量表达式或由常量表达式构造的右值进行初始化。常量表达式对象的行为类似于const对象,但是它在使用之前需要进行初始化,并且它的初始化器必须是一个常量表达式。因此,常量表达式对象始终可以作为另一个常量表达式的一部分使用。

常量表达式构造函数是通过声明constexpr关键字来定义的构造函数。它可以有一个成员初始化列表,但是它的函数体必须为空,除了typedef和static assert之外。它的参数必须具有字面类型。

常量表达式构造函数允许编译器在编译时初始化对象,前提是构造函数的参数都是常量表达式。

根据Scott Meyers的书《Effective Modern C++》,有关constexpr的一些提示:

- constexpr对象是const对象,并且在编译期间初始化;

- constexpr函数在使用编译期间已知的参数调用时产生编译期结果;

- constexpr对象和函数可以在更广泛的上下文中使用,而不是非constexpr对象和函数;

- constexpr是对象或函数的一部分接口。

从上述内容中可以看出,使用const关键字和constexpr关键字都可以用来定义常量,但是它们的使用场景有所不同。const更适用于在运行时进行初始化的常量,而constexpr更适用于在编译时进行初始化的常量。在需要编译时常量的情况下,使用constexpr可以提供更好的性能和安全性。

0
0 Comments

在C++中,我们可以使用const关键字修饰变量,从而防止其被修改。而constexpr关键字则告诉编译器,该表达式在编译时就可以确定为一个常量值,因此可以在一些需要常量值的地方使用,比如数组长度、赋值给const变量等等。这两个关键字是完全不同的概念,但是可以(而且应该)一起使用。

然而,有时候在选择使用const还是constexpr关键字时,会出现一些困惑。一个例子是en.cppreference.com/w/cpp/container/array/get中给出的constconstexpr的使用示例。在这个示例中,constexpr T f(x) const中的const修饰的是函数本身,而constexpr const T f(x)中的const修饰的是返回类型。虽然这个答案没有提到成员函数上使用const的情况,但是在实际工作中,我们也可以在成员函数上使用const关键字。

需要注意的是,const并不能完全阻止变量被修改,它只是阻止了程序员在没有显式进行类型转换的情况下修改变量。换句话说,const关键字只是一种编译时的限制,而不是运行时的限制。

为了解决constconstexpr关键字的使用问题,我们可以根据具体的需求来选择使用哪个关键字。如果我们需要一个在编译时就可以确定为常量的值,那么就应该使用constexpr关键字。而如果我们只是希望限制变量在使用过程中不被修改,那么就可以使用const关键字。

const关键字用于修饰变量,防止其被修改;而constexpr关键字用于告诉编译器,某个表达式可以在编译时确定为常量值。在实际使用中,我们可以根据需求选择使用哪个关键字。

0
0 Comments

在C++中,const和constexpr关键字都可以用于对象和函数的声明。当应用于对象时,它们之间的基本区别是:

- const声明一个对象为常量。这意味着一旦初始化,该对象的值就不会改变,并且编译器可以利用这一点进行优化。它还有助于防止程序员在初始化后修改不应修改的对象。

- constexpr声明一个对象适用于标准所称的常量表达式。但要注意,constexpr并不是唯一的实现此功能的方式。

当应用于函数时,它们之间的基本区别是:

- const只能用于非静态成员函数,而不是普通函数。它保证成员函数不会修改任何非静态数据成员(除了可变数据成员,它可以在任何情况下修改)。

- constexpr可以与成员函数和非成员函数以及构造函数一起使用。它声明函数适用于常量表达式。只有在函数满足某些条件(7.1.5/3,4)时,编译器才会接受它,最重要的是:

- 函数体必须是非虚拟的和极其简单的:除了typedef和静态断言,只允许一个return语句。对于构造函数,只允许初始化列表、typedef和静态断言。(= default和= delete也是允许的。)

- 自C++14起,对于constexpr函数的规则更加宽松,允许在constexpr函数内部使用的内容有:asm声明、goto语句、带有非case和default标签的语句、try块、非字面类型变量的定义、静态或线程存储期变量的定义、未执行初始化的变量的定义。

- 参数和返回类型必须是字面类型(通常是简单类型,如标量或聚合类型)。

常量表达式的含义:

- 常量表达式不仅仅是常量,它可以在需要在编译时求值的地方使用,例如模板参数和数组大小指定器。

- 但请注意,将某个东西声明为constexpr并不一定保证它将在编译时求值。它可以在其他需要在运行时求值的地方使用。

- 一个对象可能适用于常量表达式而没有被声明为constexpr。例如,在上述代码中,常量N被初始化为字面值,满足了常量表达式的条件,因此可以在对象声明中使用,即使它没有被声明为constexpr。

那么什么时候我真的需要使用constexpr呢?

- 对象(如上面的N)可以在没有声明为constexpr的情况下用作常量表达式。这对于满足以下条件的所有对象都成立:

- 是const的

- 是整数类型或枚举类型

- 使用声明时的常量表达式进行初始化

- 函数要适用于常量表达式,必须明确声明为constexpr。仅满足常量表达式函数的条件是不够的。

那么什么时候可以/应该同时使用const和constexpr呢?

- 对象声明中。当这两个关键字引用同一个要声明的对象时,这是不必要的。constexpr隐含了const。

- 在成员函数声明中。在C++11中,constexpr隐含const,而在C++14和C++17中不是这样的。在C++14中,为了仍然可以将成员函数用作const函数,需要将其声明为constexpr。

const和constexpr关键字在C++中具有不同的用途和语法。const用于声明常量对象和不修改数据成员的成员函数,而constexpr用于声明适用于常量表达式的对象和函数。在使用这些关键字时,需要注意它们的区别以及何时使用它们。

0