详解C++17中nodiscard标记符的使用

 更新时间:2023年02月27日 15:19:33   作者:orbitgw  
在C++ 17中引入了一个标记符nodiscard,用于声明一个 “非弃值(no-discard)表达式”。这篇文章就来和大家来聊一聊nodiscard标记符的使用吧

前言

在C++ 17中引入了一个标记符nodiscard,用于声明一个 “非弃值(no-discard)表达式”。那么在开始之前,我们需要了解一下什么是弃值表达式。

弃值表达式

弃值表达式,就是放弃获取返回值的表达式。首先弃值表达式的返回值是非void类型的。一般,我们使用的弃值表达式,其返回值只是起次要的作用,而其本身的作用占主要。比如++i;就是一个弃值表达式,它的主要作用就是累加,但同时我们也可以选择获取其累加的返回值,只不过这是次要的。

再比如,C标准库的文件写入函数,其声明如下:

int __cdecl fputs(const char * __restrict__ _Str,FILE * __restrict__ _File);

它有一个int类型的返回值,用于获取写入状态,它的主要作用是写入文件,我可以选择不获取状态,也可以选择获取状态:

fputs("Hello World",pFile);
int result = fputs("Hello World",pFile);

nodiscard标记符

那么我如果想向用户建议获取返回值,这时候,我就可以使用nodiscard标记符。它一般用于标记函数的返回值或者某个类。声明语法为:

/* @since C++17 */
[[nodiscard]] return_type function();
/* @since C++20 */
[[nodiscard("message")]] return_type  function();
/* Standard lib defination */
/*  
    #if __cplusplus >= 201703L
    # define _GLIBCXX_NODISCARD [[__nodiscard__]]
    #else
    # define _GLIBCXX_NODISCARD
    #endif
*/
_GLIBCXX_NODISCARD return_type  function();

如果一个被nodiscard标记了的表达式,如果我们在使用时弃值了,而且没有使用static_cast<void>将其转化为void时,编译器会抛出warning来提醒用户获取返回值。

函数非弃值声明

[[nodiscard]] int func1(){
    return 1;
}

[[nodiscard("nodiscared function")]] int func2(){
    return 1;
}

int main(){
    func1();                         //warning C++17
    func2();                         //warning c++20
    int a = func1();                 //no warning
    static_cast<void>(func1());      //no warning
}

结果如下:

类/枚举类/结构 非弃值声明

class [[nodiscard]] A{};
enum class [[nodiscard]] B{X,Y};
struct [[nodiscard]] C{};

A createA(){
    return A();
}

B createB(){
    return B::X;
}

C createC(){
    return C();
}

int main(){
    createA();
    createB();
    createC();
}

输出如下:

6.cpp: In function 'int main()':
6.cpp:22:12: warning: ignoring returned value of type 'A', declared with attribute 'nodiscard' [-Wunused-result]
   22 |     createA();
      |     ~~~~~~~^~
6.cpp:10:3: note: in call to 'A createA()', declared here
   10 | A createA(){
      |   ^~~~~~~
6.cpp:6:21: note: 'A' declared here
    6 | class [[nodiscard]] A{};
      |                     ^
6.cpp:23:12: warning: ignoring returned value of type 'B', declared with attribute 'nodiscard' [-Wunused-result]
   23 |     createB();
      |     ~~~~~~~^~
6.cpp:14:3: note: in call to 'B createB()', declared here
   14 | B createB(){
      |   ^~~~~~~
6.cpp:7:26: note: 'B' declared here
    7 | enum class [[nodiscard]] B{X,Y};
      |                          ^
6.cpp:24:12: warning: ignoring returned value of type 'C', declared with attribute 'nodiscard' [-Wunused-result]
   24 |     createC();
      |     ~~~~~~~^~
6.cpp:18:3: note: in call to 'C createC()', declared here
   18 | C createC(){
      |   ^~~~~~~
6.cpp:8:22: note: 'C' declared here
    8 | struct [[nodiscard]] C{};
      |                      ^

返回类引用与类指针

当返回值为引用或者指针的 类/枚举类/结构(函数不行) 时,nodiscard 就无效了:

class [[nodiscard]] A{};

A& createAref(){
    A* a = new A();
    return *a;
}

A* createAptr(){
    A* a = new A();
    return a;
}

int main(){
    createAref(); //no warning
    createAptr(); //no warning
}

到此这篇关于详解C++17中nodiscard标记符的使用的文章就介绍到这了,更多相关C++17 nodiscard标记符内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++实现将数据写入Excel工作表的示例代码

    C++实现将数据写入Excel工作表的示例代码

    直观的界面、出色的计算功能和图表工具,使Excel成为最流行的个人计算机数据处理软件。在本文中,您将学习如何使用 Spire.XLS for C++ 创建 Excel 文档,以及如何将数据写入 Excel 工作表
    2023-03-03
  • C++遍历文件夹下文件的方法

    C++遍历文件夹下文件的方法

    这篇文章主要介绍了C++遍历文件夹下文件的方法,实例分析了C++针对文件夹遍历的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • C语言音乐播放器实例代码

    C语言音乐播放器实例代码

    文章给大家分享了用C语言音乐播放器的实例代码,对此有需要的朋友参考学习下。
    2018-07-07
  • C++中用substr()函数消除前后空格的解决方法详解

    C++中用substr()函数消除前后空格的解决方法详解

    本篇文章是对C++中用substr()函数消除前后空格的方法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C++数据结构与算法的基础知识和经典算法汇总

    C++数据结构与算法的基础知识和经典算法汇总

    终是到了标志着大二结束的期末考试了,对于《算法设计与分析》这门课,我需要总结一下学过的所有算法的思想以及老师补充的关于两个复杂度和递归的概念思想,以及更深层次的理解,比如用画图的方式表达出来,我觉得可以用博客记录总结一下,分享给大家,希望能有所帮助
    2022-05-05
  • QT使用SQLite数据库超详细教程(增删改查、对大量数据快速存储和更新)

    QT使用SQLite数据库超详细教程(增删改查、对大量数据快速存储和更新)

    这篇文章主要给大家介绍了关于QT使用SQLite数据库的相关资料,其中包括增删改查以及对大量数据快速存储和更新,SQLite是一种嵌入式关系型数据库管理系统,它是一个软件库,提供了一个自包含、无服务器、零配置的、事务性的SQL数据库引擎,需要的朋友可以参考下
    2024-01-01
  • 一篇文章带你入门C语言:函数

    一篇文章带你入门C语言:函数

    这篇文章主要介绍了C语言中函数的声明、定义及使用的入门教程,重点讲述了main函数的相关知识,需要的朋友可以参考下,希望能给你带来帮助
    2021-08-08
  • C++ 线段树原理与实现示例详解

    C++ 线段树原理与实现示例详解

    这篇文章主要为大家介绍了C++ 线段树原理与实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • 使用C++实现FTP上传和下载

    使用C++实现FTP上传和下载

    当在Windows上使用C++进行FTP上传和下载时,您可以使用libcurl库来简化操作,本文将为大家详细介绍具体步骤,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-12-12
  • 浅析C语言中sscanf 的用法

    浅析C语言中sscanf 的用法

    以下是对C语言中sscanf函数的使用方法进行了详细的分析介绍,需要的朋友参考下
    2013-07-07

最新评论