自己做链接网站,东莞网页如何制作,free wordpress themes 4 u,电脑网址打不开网页怎么办C中const和constexpr的区别 一、C中的常量概念二、const关键字的用法和特点三、constexpr关键字的用法和特点四、const和constexpr的区别对比4.1、编译时计算能力4.2、可以赋值的范围4.3、对类和对象的适用性4.4、对函数的适用性4.5、性能和效率的差异 五、使用示例六、总结 一… C中const和constexpr的区别 一、C中的常量概念二、const关键字的用法和特点三、constexpr关键字的用法和特点四、const和constexpr的区别对比4.1、编译时计算能力4.2、可以赋值的范围4.3、对类和对象的适用性4.4、对函数的适用性4.5、性能和效率的差异 五、使用示例六、总结 一、C中的常量概念
在C中常量是指其数值或数值引用在程序执行期间不能被改变的变量。常量可以在程序中用来定义一些固定不变的值如数学常数、固定参数等。在C中有两种主要类型的常量const和constexpr。
const常量概念
使用关键字const声明的常量一旦赋值后便不能修改其数值具有只读属性。可以作用于变量、指针、引用以及成员函数的参数保证其在函数内部不会被修改。const在编译时起作用但是不一定要进行常量表达式的计算。
constexpr常量概念
使用关键字constexpr声明的常量必须在编译时期计算出结果并且其值在编译时即可确定。可以用于定义常量、函数等通常用于要求在编译时仅使用常量表达式的场景。constexpr在C11之后引入可用于进行更严格的编译时检查和优化。
const关键字的作用
声明一个常量即其数值在程序执行期间不能被改变。可以用于定义普通变量、类成员变量、函数参数等使其成为只读变量。通过const修饰能够避免意外的数值修改。
constexpr关键字的作用
声明一个常量表达式要求在编译时期计算出结果以产生一个编译时常量。可以用于定义常量、函数等通常用于需要在编译时进行计算的场景例如数组大小、模板参数等。constexpr在C11中引入能够进行更严格的编译时检查和优化在部分情况下可以提高程序性能。
二、const关键字的用法和特点
两种方式来声明和定义const变量 通过变量声明和定义分开的方式用于在多个文件之间共享const变量 // 声明const变量
extern const int myConst; // 声明一个外部链接的const变量// 在另一个文件中定义const变量
const int myConst 10;直接声明和定义const变量 // 声明并定义const变量
const int myConst 10;const 成员函数表示该函数不会修改对象的成员变量这样的函数可以被 const 对象调用。
示例
class MyClass {
public:void regularFunction() {// 正常的成员函数定义_val 1;}void constFunction() const {// const 成员函数定义// 在 const 成员函数中不能修改对象的成员变量}
private:int _val;
};一旦将一个成员函数声明为 const那么这个函数就不能对对象的成员变量进行任何修改操作。
const修饰符还可以用于引用和指针类型以表明它们指向的数据是常量不能被修改。
const引用可以通过在引用声明中添加const修饰符来创建const引用如下所示
int x 10;
const int ref x; // 创建一个指向常量的引用const指针同样地在指针声明中添加const修饰符可以创建const指针如下所示
int y 20;
const int* ptr y; // 创建一个指向常量的指针还可以这样声明指向常量的指针
int z 30;
int* const ptr2 z; // 创建一个常量指针const在编译时的作用 如果一个变量被声明为const则编译器可以将其视为一个常量表达式从而在编译时进行优化。即编译器可以在编译期间进行常量折叠和替换而不必在运行时再去计算这个值。 编译时类型检查使用const可以将变量声明为只读确保在编译时不会发生意外的修改。如果尝试在const变量上进行写操作编译器会报错。 const修饰指针和引用时可以指示指针和引用所指向的内容为常量这样可以在编译时进行一定的错误检查。
const的限制 常量必须进行初始化一个变量被声明为const它必须在声明时进行初始化否则编译器会报错。这是因为const在C中被设计为一种“一旦赋值不可更改”的特性。 对于const指针或引用来说虽然它们指向的值是不可修改的但是它们本身并不是常量。因此可以通过改变指针或引用的指向来改变它们指向的值这个要非常小心。
const的适用场景 固定不变的数值或变量时可以将其声明为const以确保这些值在程序的执行过程中不会被修改。 将函数的参数声明为const可以确保函数内部不会对参数进行修改同时向调用者明确表明函数的行为。 在编译时进行常量折叠和替换。
三、constexpr关键字的用法和特点
constexpr关键字用于声明变量和函数为编译时常量表达式。它可以用于在编译时求值以及在运行时提供常量值。
constexpr变量的语法
constexpr type variable_name value;其中type表示变量的类型variable_name表示变量的名称value表示变量的初始值。重点注意的是value必须是一个常量表达式必须在编译时就可以确定。
示例
constexpr int width 10; // 声明一个constexpr变量constexpr函数的语法
constexpr return_type function_name(parameters) {// 函数体return value;
}return_type表示函数返回值的类型function_name表示函数的名称parameters表示函数的参数列表value表示函数的返回值。重点注意的是constexpr函数的参数和返回值类型必须是能够在编译期间确定的常量表达式。
示例
constexpr int square(int x) {return x * x;
}注意在C14之前constexpr函数的函数体通常被要求是非常简单的例如只有一条return语句。但是在C14中放宽了这一限制允许constexpr函数包含有限的控制流、局部变量和循环。
constexpr变量的特点
通过使用constexpr关键字变量可以在编译时求值其值在编译期间就已经确定。constexpr变量必须被初始化为常量表达式。constexpr变量可以作为数组的长度、枚举的值、模板参数等。与const变量不同constexpr变量的值在编译时即确定因此可以作为编译时常量来使用。
示例
constexpr int width 10; // 定义一个编译时常量
constexpr int area width * width; // 定义一个编译时常量表达式constexpr函数的特点
通过使用constexpr关键字函数可以在编译时求值。constexpr函数通常用于执行简单的计算并且其参数和返回值都必须是能够在编译期间确定的常量表达式。constexpr函数可以在编译时被用作模板参数。
示例
constexpr int square(int x) {return x * x;
}前面说了这么多constexpr在编译时的注意事项这里再总结一下constexpr在编译时的作用 常量表达式的求值constexpr关键字告诉编译器变量或函数的值可以在编译时求值。即编译器会在编译阶段计算constexpr变量和函数的值而不是在运行时。这可以在一定程度上提高程序的性能因为编译时求值的常量表达式可以避免在运行时进行重复的计算。 编译时的优化使用constexpr可以让编译器在编译时对代码进行更多的优化。例如编译器可以在编译期间内联constexpr函数消除不必要的计算以及在一些情况下将表达式简化为常量。这可以提高程序的执行效率并减少运行时的开销。
constexpr的限制
constexpr函数必须是单一返回语句并且该语句必须返回一个常量表达式。constexpr函数在C11中还有更多的限制例如不能包含循环、局部变量和复杂的控制流但在C14中这些限制已经有所放宽。constexpr变量必须在声明时进行初始化并且初始化表达式必须是常量表达式。
constexpr的适用场景
当变量的值在编译时已知并且永远不会改变时可以使用constexpr变量。这对于一些数学常数或者其他不变的配置参数非常有用。当函数需要在编译时进行计算并且其参数和返回值都是常量表达式时可以使用constexpr函数。这可以用于在编译时生成特定的值或序列避免在运行时进行重复的计算。constexpr还可以用于模板编程中特别是对于元编程和编译时计算相关的需求。
四、const和constexpr的区别对比
4.1、编译时计算能力
const
const关键字用于声明常量它指定了一个变量的值在程序执行期间不能被修改。在编译时const常量的值是不可更改的但并不要求其在编译时进行计算。由于const变量的值在运行时不能被改变因此编译器会将const变量存储在只读存储区域中但并不要求其在编译时进行计算。
constexpr
constexpr关键字用于声明常量表达式它要求变量或函数在编译时就能得到计算结果。对于constexpr变量编译器会在编译期间进行常量表达式的求值而不是在运行时。这意味着constexpr变量的值必须在编译时就能确定。同样地constexpr函数在编译时执行并且其参数必须是常量表达式返回值也必须是常量表达式。
示例 1const
#include iostream
using namespace std;int main() {const int x 5;const int y x 3;cout y endl;return 0;
}定义了一个 const 变量 x并将其值设为 5。然后又定义了一个 const 变量 y并将其设为 x 3。这里的 x 和 y 都是在运行时确定的因此编译器会在程序运行时对 y 的值进行计算。
示例 2constexpr
#include iostream
using namespace std;int main() {constexpr int x 5;constexpr int y x 3;cout y endl;return 0;
}constexpr 来定义 x 和 y。在这种情况下编译器会在编译时就计算出 y 的值因为 x 和 3 都是在编译时就可以确定的常量。因此y 的值在编译时就被确定了。
小结const和constexpr在编译时计算能力上的区别在于const仅指示变量的值在运行时不可修改而constexpr则要求在编译时进行常量表达式的计算。constexpr更适用于那些需要在编译时确定值或进行编译时计算的场景而const更适用于普通的常量声明。
4.2、可以赋值的范围
const
const 可用于声明常量可以赋值给任何类型的变量包括全局变量、局部变量、类的成员变量和函数参数。可以通过 const 指针指向常量或者通过 const 引用绑定到常量对象但这些常量本身可以在编译时或者运行时进行初始化。
constexpr
constexpr 可以用于声明常量可以赋值给变量、函数、模板参数和构造函数的初始化器。在 C11 中constexpr 主要用于声明常量而在 C14 中constexpr 进一步扩展到了函数允许对常量表达式进行计算。constexpr 也可以用于指针和引用但是需要指向或者引用在编译时就能确定其值的对象。
const 可以用于声明各种类型的常量并且可以用于指针和引用的限制不是很严格而 constexpr 主要用于声明常量同时还可以用于指示编译时计算。constexpr 在赋值的范围上更加灵活特别是在 C14 中的扩展。
4.3、对类和对象的适用性
const
const 可以用于成员函数的声明表示该函数不会修改对象的成员变量。同时const 成员函数可以被一个 const 对象调用但不能修改其成员变量。const 对象可以调用对象的 const 成员函数但不能调用非 const 成员函数确保对象的成员变量不被修改。
constexpr
constexpr 关键字在类的成员函数中表示该函数可以在编译时求值可以用于构造函数、成员函数和类的静态成员函数。对于构造函数可以使用 constexpr 来声明编译时可求值的构造函数要求构造函数中只能包含编译时可计算的操作。constexpr 成员函数可以在编译时求值适用于一些固定值的计算在 C14 中可以用 constexpr 成员函数替换类中的静态常量成员。
当涉及到赋值的范围const 和 constexpr 也有一些不同。让我们通过示例来说明这一点。
示例 1const
#include iostream
using namespace std;int main() {const int x 5;const int* ptr x; // 指向常量的指针cout *ptr endl;*ptr 10; // 编译器会报错因为指针指向的是一个常量return 0;
}示例 2constexpr
#include iostream
using namespace std;int main() {constexpr int x 5;constexpr int* ptr x;cout *ptr endl;*ptr 10; // 编译器会报错因为指针指向的是一个常量return 0;
}小结const 主要用于指示对象或者成员函数不可修改限定对象的只读访问行为而 constexpr 用于指示在编译时可以进行求值的场景特别适用于一些对值就能确定的操作。constexpr 对于类和对象的适用性更加注重在编译时进行的操作而 const 更多是关于对象的只读性质。
4.4、对函数的适用性
const
const 可以用于函数参数和函数返回值的声明。在函数参数中const 可以表示该参数不会被修改在函数返回值中const 可以表示返回的值为常量。const 成员函数可以用于表示该函数不会修改对象的成员变量在类中通过 const 关键字来声明成员函数以确保其在调用过程中不会修改对象的状态。
constexpr
constexpr 可以用于函数声明表示该函数可以在编译时求值。在 C11 中constexpr 主要用于常量表达式而在 C14 中扩展到了允许对更复杂的函数进行编译时求值。在 C14 中constexpr 还可以用于标记类的成员函数以及构造函数和析构函数表示在编译时就能确定其值或者执行结果的函数。
示例 1const
#include iostream
using namespace std;void printMessage(const string msg) {cout msg endl;
}int main() {const string message Hello, world!;printMessage(message);return 0;
}示例 2constexpr
#include iostream
using namespace std;constexpr int square(int x) {return x * x;
}int main() {constexpr int num 5;constexpr int result square(num);cout result endl;return 0;
}小结const 主要用于标记函数参数和返回值的常量性质以及在类中用于声明不会修改对象状态的成员函数而 constexpr 则主要用于表示可以在编译时求值的函数适用于对一些值在编译时就能确定的操作。constexpr 对于函数的适用性更加注重在编译时进行的操作而 const 则更多用于标记常量性质。
4.5、性能和效率的差异
const和constexpr的主要区别在于编译时进行的操作和值的确定性。
const:
const 定义的常量在运行时是不可修改的但它的值是在运行时确定的。const 变量的值在编译时可能无法确定因此每次使用时都需要进行运行时计算。当 const 变量被频繁地使用并且其值是运行时计算得到的时候const 可能会导致性能下降。
constexpr:
constexpr 在编译时就能确定其值因此可以用于在编译时进行计算。使用 constexpr 可以提高程序的性能和效率因为它在编译时就能确定值而不需要在运行时进行计算。constexpr 变量可以在编译时被替换为其确定的值这样可以减少程序运行时的开销。
示例 1const
#include iostream
#include vector
using namespace std;void printVector(const vectorint vec) {for (const int num : vec) {cout num ;}cout endl;
}int main() {const int size 1000000;vectorint numbers;for (int i 0; i size; i) {numbers.push_back(i);}printVector(numbers);return 0;
}示例 2constexpr
#include iostream
using namespace std;constexpr int square(int x) {return x * x;
}int main() {constexpr int num 5;constexpr int result square(num);cout result endl;return 0;
}从性能和效率的角度来看constexpr 在编译时确定值的特性使得它更有可能比 const 变量更有效率。因为它减少了在运行时进行计算的需要可以在适当的情况下提高程序的性能。但对于一般的常量定义使用 const 或者 constexpr 都不会对程序的性能产生显著的影响。
五、使用示例
// 使用 const 定义常量
#include iostream
using namespace std;int main() {const int max_value 100;cout The maximum value is: max_value endl;// max_value 200; // 这行代码会导致编译错误因为常量不可更改return 0;
}// 使用 constexpr 定义常量
#include iostream
using namespace std;int main() {constexpr int max_value 100;cout The maximum value is: max_value endl;return 0;
}六、总结
const
const 变量在编译时不一定会被计算出具体的值它可以是一个运行时才能得到的值。所以const 变量不能用于需要在编译期间计算值的场合。const 变量可以存储在内存中并可以被编译器优化。const 变量可以用于任何场合包括函数参数、类成员等。
constexpr
constexpr 变量必须在编译时期就能得到一个确定的值其值必须能够在编译时计算得出所以一般用于需要在编译期确定常量值的场合。constexpr 变量更多的是被视为一个编译时的常量表达式在一些需要常量表达式的地方必须使用 constexpr。constexpr 允许编译器在编译时进行计算并且可以在一些上下文中被用于要求常量表达式的场合比如数组大小、模板参数等。
常量有不同的用法和适用场景 const变量 用法可以通过const关键字定义一个不可改变的变量如const int a 10;适用场景常用于定义一个在程序执行过程中其值不会改变的变量例如常数、固定参数等。 constexpr变量 用法可以使用constexpr关键字定义一个编译时常量要求在编译时期就能得到一个确定的值。适用场景常用于要求在编译期计算得到值的场合例如定义数组大小、模板参数、常量表达式等。 #define预处理器宏 用法可以通过#define指令定义一个常量宏如#define PI 3.14159适用场景常用于定义一些简单的常量例如数学常数、特定数值、标志位等。 枚举类型(enum) 用法可以通过enum关键字定义一组具名的整型常量如enum Week {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};适用场景常用于定义一组相关的常量例如星期、状态码等。