C++ 14 17 新特性:[[fallthrough]], [[nodiscard]], [[maybe_unused]], 和 [[deprecated]] 新属性的使用...

简介: C++ 14 17 新特性:[[fallthrough]], [[nodiscard]], [[maybe_unused]], 和 [[deprecated]] 新属性的使用...

1. C++ 14 17 新增的属性

  1. [[fallthrough]] 属性:这个属性用于在switch语句中。通常,当switch语句的一个case执行完毕后,会自动跳转到switch语句的末尾,除非存在break语句。如果你想要故意从一个case“落入”(fall through)到下一个case,可以使用[[fallthrough]]属性来告诉编译器这是故意的行为,以避免编译器发出警告。
  2. [[nodiscard]] 属性:这个属性可以用于函数或者返回类型。它的作用是告诉编译器:调用这个函数时,它的返回值不应被忽略。如果程序员调用了这样的函数但没有使用它的返回值,编译器会发出警告。这对于那些返回重要状态或错误码的函数特别有用。
  3. [[maybe_unused]] 属性:此属性可以用于声明变量、函数、类型等。它告诉编译器,即使这个实体(变量、函数等)没有被使用,也不应该产生未使用的警告。这在编写可能在某些情况下不使用但在其他情况下使用的代码时很有用。
  4. [[deprecated]] 属性:这个属性用于标记变量、函数、类型等已经被弃用。当其他代码尝试使用被标记为弃用的实体时,编译器会发出警告。这通常用于代码库的迁移和升级,提示开发者某些功能在未来的版本中可能会被移除或更改。

2. 示例

当然可以。下面我将为每个属性提供一个简单的示例:

  1. [[fallthrough]] 属性示例:
switch (value) {
    case 1:
        //... 一些代码 ...
        [[fallthrough]]; // 明确指出接下来会执行 case 2 的代码
    case 2:
        //... 一些代码 ...
        break;
    default:
        //... 一些代码 ...
        break;
}
  1. [[nodiscard]] 属性示例:
[[nodiscard]] int computeValue() {
    return 42;
}
void example() {
    computeValue(); // 这里如果不使用返回值,编译器可能会警告
    int value = computeValue(); // 正确使用返回值
}
  1. [[maybe_unused]] 属性示例:
void example([[maybe_unused]] int unusedParam) {
    // 这个函数的参数可能不会被使用
    //... 一些代码 ...
}
[[maybe_unused]] int unusedVariable = 10; // 这个变量可能不会被使用
  1. [[deprecated]] 属性示例:
[[deprecated("Use newFunction() instead")]]
void oldFunction() {
    //... 一些代码 ...
}
void newFunction() {
    //... 一些代码 ...
}
void example() {
    oldFunction(); // 调用此函数时,编译器会发出弃用警告
    newFunction(); // 正确的函数调用
}

这些示例展示了如何在C++代码中使用这些属性。记住,这些属性的主要目的是提供额外的信息给编译器,帮助程序员写出更清晰、更安全的代码。

3. 适合的场景

各个属性适用的场景如下:

  1. [[fallthrough]] 属性的适用场景
  • 故意的case穿透:在switch语句中,当你有意让一个case块落入(fall through)到下一个case块中时使用。这在某些逻辑处理中很常见,比如在一系列条件中共享相同的代码块。
  • 提高代码可读性:即使逻辑上允许case穿透,不使用[[fallthrough]]也可能导致维护者误解代码意图。使用这个属性可以明确指出这是有意为之,而不是编码错误。
  1. [[nodiscard]] 属性的适用场景
  • 重要的返回值:用于那些返回值十分重要的函数,比如错误检查、状态检索或计算结果,这些返回值忽视了可能导致逻辑错误或资源泄露。
  • API设计:在设计库或API时,强制调用者处理返回值,特别是对于那些可能返回错误码或状态的函数。
  1. [[maybe_unused]] 属性的适用场景
  • 条件编译:在代码中使用条件编译时(如使用#ifdef),某些变量或函数可能只在特定条件下使用。使用[[maybe_unused]]可以避免在未使用这些变量或函数时产生警告。
  • 框架或库代码:在编写通用代码或库时,某些参数可能不总是被使用,但为了保持接口的一致性,仍需要声明它们。
  1. [[deprecated]] 属性的适用场景
  • 代码迁移和升级:在软件开发过程中,当某个函数或类被新的实现所替代时,标记旧版本为弃用,引导开发者使用新版本。
  • 向后兼容性:在维持向后兼容性的同时,提醒开发者某些特性在未来版本中可能会被移除或更改,鼓励他们迁移到更新的实现。
  • 避免使用不安全或过时的代码:对于已知存在问题或不再推荐使用的代码,使用[[deprecated]]属性可以减少其在新开发中的使用。

通过在适当的场景使用这些属性,可以提高代码的安全性、可维护性和清晰度。

结语

在我们的编程学习之旅中,理解是我们迈向更高层次的重要一步。然而,掌握新技能、新理念,始终需要时间和坚持。从心理学的角度看,学习往往伴随着不断的试错和调整,这就像是我们的大脑在逐渐优化其解决问题的“算法”。

这就是为什么当我们遇到错误,我们应该将其视为学习和进步的机会,而不仅仅是困扰。通过理解和解决这些问题,我们不仅可以修复当前的代码,更可以提升我们的编程能力,防止在未来的项目中犯相同的错误。

我鼓励大家积极参与进来,不断提升自己的编程技术。无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力。

目录
相关文章
|
4天前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
33 12
|
6月前
|
编译器 程序员 定位技术
C++ 20新特性之Concepts
在C++ 20之前,我们在编写泛型代码时,模板参数的约束往往通过复杂的SFINAE(Substitution Failure Is Not An Error)策略或繁琐的Traits类来实现。这不仅难以阅读,也非常容易出错,导致很多程序员在提及泛型编程时,总是心有余悸、脊背发凉。 在没有引入Concepts之前,我们只能依靠经验和技巧来解读编译器给出的错误信息,很容易陷入“类型迷路”。这就好比在没有GPS导航的年代,我们依靠复杂的地图和模糊的方向指示去一个陌生的地点,很容易迷路。而Concepts的引入,就像是给C++的模板系统安装了一个GPS导航仪
206 59
|
5月前
|
安全 编译器 C++
【C++11】新特性
`C++11`是2011年发布的`C++`重要版本,引入了约140个新特性和600个缺陷修复。其中,列表初始化(List Initialization)提供了一种更统一、更灵活和更安全的初始化方式,支持内置类型和满足特定条件的自定义类型。此外,`C++11`还引入了`auto`关键字用于自动类型推导,简化了复杂类型的声明,提高了代码的可读性和可维护性。`decltype`则用于根据表达式推导类型,增强了编译时类型检查的能力,特别适用于模板和泛型编程。
51 2
|
6月前
|
存储 编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(三)
【C++】面向对象编程的三大特性:深入解析多态机制
|
6月前
|
存储 编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(二)
【C++】面向对象编程的三大特性:深入解析多态机制
|
6月前
|
编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(一)
【C++】面向对象编程的三大特性:深入解析多态机制
|
6月前
|
C++
C++ 20新特性之结构化绑定
在C++ 20出现之前,当我们需要访问一个结构体或类的多个成员时,通常使用.或->操作符。对于复杂的数据结构,这种访问方式往往会显得冗长,也难以理解。C++ 20中引入的结构化绑定允许我们直接从一个聚合类型(比如:tuple、struct、class等)中提取出多个成员,并为它们分别命名。这一特性大大简化了对复杂数据结构的访问方式,使代码更加清晰、易读。
87 0
|
6月前
|
存储 编译器 C++
【C++】面向对象编程的三大特性:深入解析继承机制(三)
【C++】面向对象编程的三大特性:深入解析继承机制
|
6月前
|
编译器 C++
【C++】面向对象编程的三大特性:深入解析继承机制(二)
【C++】面向对象编程的三大特性:深入解析继承机制
|
6月前
|
安全 程序员 编译器
【C++】面向对象编程的三大特性:深入解析继承机制(一)
【C++】面向对象编程的三大特性:深入解析继承机制