2026/1/18 9:24:18
网站建设
项目流程
网站建设代码好难啊,济南易搜的网站建设,wordpress管理员 404,企业网站建设 租用服务器一、说明
前面多篇文章分析了常量的各种用法以及在新标准中的各种扩展。到目前为止#xff0c;可以发现有几个长得差不多的关键字#xff1a;从早期的const到C11中的constexpr直到C20中的consteval和constinit。这些长得类似的const有什么区别和联系呢#xff1f;下面就对它…一、说明前面多篇文章分析了常量的各种用法以及在新标准中的各种扩展。到目前为止可以发现有几个长得差不多的关键字从早期的const到C11中的constexpr直到C20中的consteval和constinit。这些长得类似的const有什么区别和联系呢下面就对它们的具体应用进行分析和说明。二、对比和分析针对上面的这些长得差不多关键字主要有以下的不同const它是在C中传统const主要用来控制运行时对变量和表达式的只读性的控制。目的在于保护相关数据的安全性并进行接口的约束。其约束的变量可以根据时机在编译期或运行期进行求值constexprC11中引入的constexpr用于在编译期的计算也就是编译期求值同时对变量和表达式的只读性控制。可以将运行期的计算转到编译期的计算和常量表达式的处理当然也支持运行期的处理consteval作为C20引入的constexpr主要用于立即函数处理即它只能修饰函数它修饰的函数及相关调用及相关求值都强制要求必须在编译期完成constinitconstinit也是C20引入的它只能用于对静态或线程局部变量进行“常量初始化”constant initialization即编译期完成初始化。否则会报编译错误。需要注意的是它只能是初始化完成后这个变量是可以再次修改的即这个变量不是常量。三、应用场景和限制分析在了解上它们四个关键字的情况后就可以根据其特点来确定其应用场景编译期计算需要在编译期计算的场景下可以使用constexpr和consteval这样就可以把运行时的开销转移到编译期。另外在模板和元编程中这两个关键字也是经常使用的接口约束和数据只读在与旧代码兼容以及需要接口的常量化控制并且只是需要对数据常量化的处理时可以考虑使用const。当然很多情况下也可以使用constexpr强制常量初始化在前面也提到过在C库中的全局静态变量调用时可能会产生初始化顺序的问题从而产生意想不到的问题。而如果使用constinit则可以避免相关变量动态初始化从而保证变量的依赖安全性。此外在全局配置处理、跨编译单元的变量以及线程局部存储等场景下都可以应用虽然constinit无法限制变量的常量性但它却也不允许联合使用const和constexpr来限制变量的常量性只读性。而const和constexpr则可以联合使用不过是一种冗余的应用没有什么实际意义。四、例程下面看一下具体的例程的对比//下面代码来自 cppreference//constexprconstexprintf();constexpr bool b1noexcept(f());// false, undefined constexpr functionconstexprintf(){return0;}constexpr bool b2noexcept(f());// true, f() is a constant expression//constevalconstevalintsqr(intn){returnn*n;}constexprintrsqr(100);// OKintx100;intr2sqr(x);// Error: Call does not produce a constantconstevalintsqrsqr(intn){returnsqr(sqr(n));// Not a constant expression at this point, but OK}constexprintdblsqr(intn){return2*sqr(n);// Error: Enclosing function is not consteval// and sqr(n) is not a constant}//constinitconstchar*g(){returndynamic initialization;}constexprconstchar*f(bool p){returnp?constant initializer:g();}constinitconstchar*cf(true);// OK// constinit const char* d f(false); // error代码很简单重点是对比一下。下面再看一个综合的应用#includemutex#includestringintBASE_V0;class Demo{public:// constexprstaticconstexprdoublePI3.14;// constevaltemplatetypename TconstevalstaticTratioPI(T t){returnt*PI;}// constexpr-运行和编译期均可用templatetypename TconstexprstaticTless(T min,T max){returnminmax;}// consttemplatetypename Tstaticconstautoget(constTt){returnBASE_Vt?BASE_V:1;}};class ControlMsg{public:voidaddmsg(conststd::stringmsg){std::lock_guardlock(mutex_);msg_.append(msg);}private:std::string msg_;std::mutex mutex_;};// constinitconstinit ControlMsg msg;// 使用示例intmain(){// 编译时constexprdoublenPIDemo::ratioPI(3.0);static_assert(nPIDemo::PInPI5*Demo::PI);// 运行时autostatusDemo::less(3,5);//常量初始化msg.addmsg(Application started);return0;}五、总结有对比才有差距才好掌握这四个关键字各自的特点和应用的场景。在实际应用的过程中要根据实际情况来有针对性使用这些关键字。特别需要注意C标准的版本不同的情况下应用方式的不同。这样才能够编写出安全、高效的C代码。