欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > C++学习笔记----10、模块、头文件及各种主题(五)---- 核心语言特性的特性测验宏与静态关键字

C++学习笔记----10、模块、头文件及各种主题(五)---- 核心语言特性的特性测验宏与静态关键字

2025/9/26 15:50:43 来源:https://blog.csdn.net/weixin_71738303/article/details/143584099  浏览:    关键词:C++学习笔记----10、模块、头文件及各种主题(五)---- 核心语言特性的特性测验宏与静态关键字

1、核心语言特性的特性测验宏

        可以使用特性测试宏来检测哪些核心语言特性被编译器支持。所有这些宏都以__cpp_或__has_cpp_开头。下面是一些例子。咨询你喜欢的c++指南获取所有可能的核心语言特性测验宏的完整列表。

➤ ➤ __cpp_range_based_for

➤ ➤ __cpp_binary_literals

➤ ➤ __cpp_char8_t

➤ ➤ __cpp_generic_lambdas

➤ ➤ __cpp_consteval

➤ ➤ __cpp_coroutines

➤ ➤ . . .

➤ ➤ __has_cpp_attribute([attribute_name])

➤ ➤ . . .

        当特定的特性添加或更新时,这些宏的值是一个代表月与年的数字。日期的格式为YYYYMM。例如,__cpp_binary_literals的值为201304,也就是说,2013年4月,这是进制常量引入的日期。另外一个例子,__has_cpp_attribute(nodiscard)的值为201603,也就是说,是2016年3月,它是[[nodiscard]]属性首次引入的日期。或者可能是201907,也就是说,2019年7月,是该特性被更新允许指定比如[[nodiscard("Reason")]]的原因的日期。

        所有这些核心语言特性测验宏不需要包含任何特定的头文件就可用。下面是一个使用的例子:

import std;using namespace std;int main()
{
#ifdef __cpp_range_based_forprintln("Range-based for loops are supported!");
#elseprintln("Bummer! Range-based for loops are NOT supported!");
#endif
}

        我们以后会解释有一些类似的标准库属性的特性测验宏。

        注意:除非书写跨平台与跨编译器代码,否则很少需要这些特性测验宏。在那种情况下,可能想知道如果特定的功能被给定的编译器支持,这样如果属性缺失的话可以提供回滚代码。我们以后会讨论跨平台开发。

2、static关键字

        在c++中关键字static有几种用法,看起来都不相关。“重载”该关键字的部分出发点是尝试避免必须引入新的关键字到语言中来。该关键字的一种使用方法在本章的连接内容中进行了讨论。其它的在本节讨论。

2.1、static数据成员与成员函数

        可以声明类的static数据成员与成员函数。static数据成员不像非static数据成员,不是每个对象的部分,只有数据成员的一个拷贝,存在于该类任何对象的外部。

        static成员函数在类层次而浊在对象层次上类似。static成员函数不在特定的对象上执行;因此,没有隐式的this指针。这也意味着static成员函数不能被标记为const。

        前面的章节提供了static数据成员与成员函数的例子。

2.2、函数中的static变量

        C++中static关键字的另一个用法是用于在范围内的出口与入口生成保持它们的值。例如,函数内的static本地变量就像一个全局变量一样,只能通过函数来访问。static变量的一个常用使用场景是“记住”一个特定的初始化是否在特定的函数中被执行。例如,使用这项技术的代码可能看起来像这样:

void performTask()
{static bool initialized{ false };if (!initialized) {println("initializing");// Perform initialization.initialized = true;}// Perform the desired task.
}

        然而,static变量可能会令人迷惑,有更好的方式来结构化你的代码,以便可以避免。在这种情况下,可能想写一个类,构造函数来执行所需的初始化。

        注意:避免使用单独的static变量。而要在对象内维护其状态。

        有时候,然而,它们是有用的。一个例子就是实现Meyers的单一设计模式,我们以后再介绍。

        注意:performTask()的实现不是线程安全的;它包含了比赛的情况。在一个多线程的环境下,需要使用原子的或其它技术来保持多线程的同步。多线程我们也在以后讨论。

2.3、非本地变量的初始化顺序

        在结束static变量主题的讨论之前,考虑一个这样的变量的初始化顺序。所有的全局与static变量在程序中被初始化在main()开始之前。在给定源文件中的变量以在源文件中出现的顺序进行初始化。例如,在下面的文件中,Demo::x保证在y之前被初始化:

class Demo
{
public:static int x;
};int Demo::x{ 3 };
int y{ 4 };

        然而,对于不同源文件中的非本地变量的初始化顺序,c++没有提供规格与保证。如果有一个全局变量x在一个源文件中,一个全局变量y在另一个源文件中,是没有办法知道哪个先被初始化的。正常情况下,这种规格的缺失不会引起任何问题。然而,如果一个全局或static变量彼此依赖可能就有问题了。回想一下,对象的初始化意味着运行其构造函数。一个全局对象的构造函数可能会访问另一个全局对象,假定它是早就被构建了的。如果这两个对象被声明在两个不同的源文件中,无法知道哪个先构建,哪个后构建,也就无法控制初始化顺序。对于不同的编译器甚至同一编译器的不同版本,其顺序可能不同,当你只是给项目添加了另外一个文件,其顺序也可能会变化。

        警告:非本地变量在不同的源文件中的初始化顺序是未定义的。

2.4、非本地变量的析构顺序

        非本地变量以初始化的相反顺序被析构。不同源文件中的非本地变量以未定义的顺序被初始化,意味着析构的顺序也是未定义的。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词