C++17新特性

前项目 C++使用的时 C++14标准,考虑到与时俱进, C++20也基本上确定,不过由于目前使用的 linux(uos)上的自带 gcc并不能全面支持 C++20, 所以暂时考虑新项目上 C++17新标准,并且写一篇完整的C++17中项目可能用到的新特性简单文档

visual studio 2019 需要添加编译参数 /std:c++17

带初始化器的 if语句

example

std::map map;
map["nihao"] = 1;
map["shijie"] = 2;
if (auto ret = map.begin(); ret != map.end()) {
  std::cout << ret->first << ": " << ret->second;
}

constexpr if 语句中,条件 的值必须是可按语境转换到 bool 类型的经转换常量表达式。若其值为 true,则舍弃 false分支语句(若存在),否则舍弃 true分支语句。

通常我们写业务很难用到,在模板元编程中会特别有用

example

template
void TestConstexprIf(T value) {
    if constexpr (std::is_integral_v)
        std::cout << "is integral" << std::endl;
    else
        static_assert(false, "T必须是整型");
}

inline 变量用来解决一个问题,全局变量再头文件中定义之后多出使用产生符号重定义错误

错误例子

// test.h 头文件
int test = 10;

// test1.cpp
void Function1() {
  test = 20;
}

// test2.cpp
void Function() {
  test = 30;
}

// 上面的代码编译将会产生重定义错误,c++17之前解决方案是使用extern导出全局变量

// 解决方案

// test.h 头文件
extern int test;

// test.cpp
int test = 10;

C++17 之后引入 inline变量使其全局变量可以直接再头文件中声明定义

example

inline int test = 10;

example

属性为各种由实现定义的语言扩展(例如 GNUIBM 的语言扩展 __attribute__((...)),微软的语言扩展 __declspec() 等)提供了统一化的语法。

[[fallthrough]] 标准属性

指示从前一标号直落是有意的,而在发生直落时给出警告的编译器不应诊断它。

C++17 之前的标准下, 有如下代码

switch (device.status())
{
case sleep:
   device.wake();
   // fall thru
case ready:
   device.run();
   break;
case bad:
   handle_error();
   break;
}

C++17 可以这样写

switch (device.status())
{
case sleep:
   device.wake();
   [[fallthrough]];
case ready:
   device.run();
   break;
case bad:
   handle_error();
   break;
}

再之前的代码编译器会告诉你没有 break的警告,但是再 c++17中使用 fallthrough属性就可以消除这个警告了

[[maybe_unused]] 标准属性

可用来消除未使用的函数和变量编译器所发出的警告

example

[[maybe_unused]] bool testUnusedVariable = true;

[[maybe_unused]]
void TestUnusedFunction() {

}

[[nodiscard]] 标准属性

如果你的某个函数的返回值特别重要,希望使用者不要忽略,可以添加这个属性,再编译的时候如果函数使用者没有使用返回值将会有一个警告产生

example

[[nodiscard]] bool TestNodiscard() {
    return true;
}

[[deprecated]] 标准属性

提示允许使用声明有此属性的名称或实体,但因为一些原因不鼓励使用,一般用在即将废弃的函数,但是还有老的用户使用到了这个函数

example

// 再vs中这个会不是警告而是错误.

[[deprecated("test deprecated")]] bool TestDeprecated() {
    return true;
}

[[noretrun]] 标准属性

告知函数并没有返回值

example

[[noreturn]] void TestNoreturn() {

}

C++17 中特别新增的一个特别好用且重要的特性, string_view相对于 string来说就是一个只读的 stringstring_view的赋值操作的空间成本和时间成本远远胜于 stringstring_view的赋值特别像一个指针的赋值,一般来说再一下情况下使用 string_view会更合适

exampel

// 常量string
const std::string = "hello world";
// string_view 更为合适
const string_view = "hello world";

// 函数参数
void Function1(const std::string& arg1) {

}

// string_view 更为合适
void Function1(string_view arg1) {

}

在没有 C++17时一直就使用 experiment/filesystem,在 C++17 filesystem被正式纳入 C++标准库中, 由于大多数人对 filesystem都比较熟悉了,在这里只是简单的介绍一下

example

std::filesystem::path path("testpath");
if (std::filesystem::exists(path)) {
  // 存在
} else {
  // 不存在
}

any是一个可用于任何类型单个值的类型安全容器,如果你之前有了解过 boost相信对这个 any类已经非常熟悉了

example

std::any Int = 69;
std::any Double = 69.123;
std::any String = std::string_view("Hello");

std::cout << Int.type().name() << std::endl;
std::cout << Double.type().name() << std::endl;
std::cout << Double.type().name() << std::endl;

std::vector anys = { Int, Double, String };
std::cout << std::any_cast(Int) << std::endl;
std::cout << std::any_cast(Double) << std::endl;
std::cout << std::any_cast(String) << std::endl;

    // has_value: 是否有值
std::any a = 1;
if (a.has_value()) {
  std::cout << a.type().name() << std::endl;// i
}

// reset:清空容器
a.reset();
if (a.has_value()) {
  std::cout << "no value\n";// no value
}

熟悉 boost的也应该非常熟悉 optional了,它最常用的地方是在你返回值是 string或者 int等出现错误之后非常隐式的表达的地方,使用 std::optional就可以帮你解决这种问题

example

[[nodiscard]]
std::optional TestOptional() {
    // 之前我们可能需要使用return -1,代表错误,现在使用st::optional就不需要那种太过于隐式的表达
    if (true) {
        return 9999;
    } else {
        return std::nullopt;
    }
}

[[nodiscard]]
std::optional TestOptional2() {
    // 之前我们可能需要使用return -1,代表错误,现在使用st::optional就不需要那种太过于隐式的表达
    if (true) {
        return "helloworld";
    } else {
        return std::nullopt;
    }
}

// optional
auto result = TestOptional();
if (result.has_value()) {
  // 有值,代表成功
} else {
  // result没有值代表失败
}

// 这个value_or表示当TestOptional的返回值为nullopt时使用or里面的值
auto ret = TestOptional2().value_or("");

variant用来表示一个类型安全的联合体, variant 的一个实例在任意时刻要么保有其一个可选类型之一的值,要么在错误情况下无值。
variant 不容许保有引用、数组,或类型 void, 空 variant可以使用 std::variant<std::monostate></std::monostate>

下面这个例子是一个实际接口设计时利用std::variant解决不同类型不同参数的接口

// variant
struct SystemProxyConfig {
  bool isService;
};

struct CustomProxyConfig {
  bool isFile;
  std::string pathOrContent;
};
std::variant config;
//config = CustomProxyConfig{ false, "http://192.168.21.161/spiderweb.pac" };
config = SystemProxyConfig{ false };
if (std::get_if(&config)) {
  // 类型成功
  CustomProxyConfig customConfig = std::get(config);
} else {
  // 类型失败
  SystemProxyConfig systemProxyConfig = std::get(config);
  int i = 0;
}

executionC++STL算法库提供了一种算法的执行策略设置,目前支持的策略:

  • sequenced_policy (顺序执行策略)
  • parallel_policy (并行执行策略)
  • parallel_unsequenced_policy (并行及无序执行策略)
  • unsequenced_policy (无序执行策略)

example

    std::vector testExecution{ 1, 2, 3, 4, 5,8, 19, 20 ,30,40,50,0,102,40,10,30,20,1000,32,31,34,45};
    auto it1 = std::find(std::execution::seq, testExecution.begin(), testExecution.end(), 5);
    auto it2 = std::find(std::execution::par, testExecution.begin(), testExecution.end(), 5);
    auto it3 = std::find(std::execution::par_unseq, testExecution.begin(), testExecution.end(), 5);

Original: https://www.cnblogs.com/gd-luojialin/p/15028180.html
Author: gd_沐辰
Title: C++17新特性

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/535424/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • C#与C++之间类型的对应

    Windows Data Type .NET Data Type BOOL, BOOLEAN Boolean or Int32 BSTR String BYTE Byte CHAR…

    C++ 2023年5月29日
    088
  • [C++] 左值、右值、右值引用

    lvalue 代表了对象,可通过取地址符获取地址,可赋值。L 可看做 location。 rvalue 代表了数据,不能获取内存地址,不可赋值。 rvalue 不能当做 lvalu…

    C++ 2023年5月29日
    055
  • 邻接表有向图(二)之 C++详解

    邻接表有向图是指通过邻接表表示的有向图。 上面的图G2包含了”A,B,C,D,E,F,G”共7个顶点,而且包含了” 上图右边的矩阵是G2在内存中…

    C++ 2023年5月29日
    077
  • c++ 数字类型转string

    include using namespace std; std::to_string(x) 几乎所有的数字类型都可以转 桂棹兮兰桨,击空明兮溯流光。 Original: http…

    C++ 2023年5月29日
    045
  • 右值引用与转移语义(C++11)

    参考资料: 左值和右值定义: C++( 包括 C) 中所有的表达式和变量要么是左值,要么是右值。通俗的 左值的定义就是非临时对象(可以取地址,有名字),那些可以在多条语句中使用的对…

    C++ 2023年5月29日
    073
  • C++类中静态数据成员MAP如何初始化

    cpp;gutter:true; conv_xxx.hpp</p> <p>class convolution { …</p> <pre…

    C++ 2023年5月29日
    061
  • 从三个语言(C++,Java,C#)的几个性能测试案例来看性能优化

    随着时间的发展,现在的虚拟机技术越来越成熟了,在有些情况下,Java,.Net等虚拟机密集计算的性能已经和C++相仿,在个别情况下,甚至还要更加优秀。本文详细分析几个性能测试案例,…

    C++ 2023年5月29日
    081
  • Guide into OpenMP: Easy multithreading programming for C++

    The for construct splits the for-loop so that each thread in the current team handles a di…

    C++ 2023年5月29日
    071
  • C++11智能指针处理Array对象

    //C++11的//完全可以避免写手动的delete代码,//但是它默认使用delete删除对象,//如果是数组对象,需要指定自定义的删除方法,支持delete[]std::sha…

    C++ 2023年5月29日
    045
  • C++ 引用计数

    原址: https://blog.csdn.net/u012501459/article/details/48229399 C++没有像java那样的垃圾回收机制,但是我们可以实现…

    C++ 2023年5月29日
    080
  • c++对象工厂

    一.简单工厂 #pragma once struct IObjectA { virtual void Test1()=0; }; class ObjectA:public IObj…

    C++ 2023年5月29日
    062
  • [C++] new和delete运算符使用方法

    new 和 delete 是C++语言中的两个运算符,配套使用。 new:用于分配内存,与C语言中的 malloc 相同,分配在堆内存 delete:用于释放内存,与C语言中的 f…

    C++ 2023年5月29日
    061
  • 【转】C++的赋值构造函数(赋值运算符重载)

    当一个类的对象向该类的另一个对象赋值时,就会用到该类的赋值构造函数。 当没有重载赋值构造函数(赋值运算符)时,通过默认赋值构造函数来进行赋值操作 注意:这里a,b对象是已经存在的,…

    C++ 2023年5月29日
    056
  • 您的第一个C++Builder程序(Hello, world!)

    最近有些老旧的项目是C++Builder开发的,虽然和Delphi的IDE的界面和操作十分相似,但是还是找本《C++ Builder 5 Developer’s Gui…

    C++ 2023年5月29日
    069
  • windows下使用vscode编写运行以及调试C/C++

    c++本地运行和debughttps://www.cnblogs.com/TAMING/p/8560253.html 运行C++/C代码 在终端运行 文件读入https://blo…

    C++ 2023年5月29日
    055
  • 关于C++单件模式释放对象

    最近接触的一个项目要用到单件模式,我像往常一样哒哒(敲击键盘ing)一个单件模式的典型结构很快就出现在我的面前: 不知道为什么,这次突然觉得new这个单词太耀眼了,熟悉c++的程序…

    C++ 2023年5月29日
    046
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球