IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++17新特性 -> 正文阅读

[C++知识库]C++17新特性

关键字

constexpr

  • 扩展constexpr使用范围,可作用与if和lambda表达式
template <bool ok>
constexpr void func()
{
	constexpr if(ok)
	{
		cout << "ok";//若ok为true,则else不参与编译
	}
	else
	{
		cout << "not ok";//若ok为false,则if不参与编译
	}
}

constexpr auto fnSub = [](int a, int b)
{
	return a + b;
}
fnSub(10, 20);//编译期间得出结果 30

static_assert

  • 扩展static_assert用法,静态断言的显示文本可选
  • static_assert(true, ""); static_assert(true);

auto

  • 扩展auto的推断范围,在c++ 11 中,auto不能定义数组。现在c++ 17 可以。
    auto x1 = { 1, 2 }; //推断出std::initializer_list<int>类型
    auto x2 = { 1, 2.0 }; //错误:类型不统一,无法推断
    auto x3{ 1, 2 }; //错误:auto的聚合初始化只能一个元素
    auto x4 = { 3 }; //推断出std::initializer_list<int>类型
    auto x5{ 3 }; //推断出int类型

typename

  • 扩展用法,允许出现在模板的模板的参数中
template <template<typename T> typename V>
struct test
{
	V<double> y;
};

inline

  • 扩展inline用法,可用于定义内联变量,C++17之前在头文件定义变量时需用extern导出,现在只需要加个inline
    inline int a = 10;

u8

  • 添加在常量字符串前,表示这是一个utf-8编码的字符串:char str[] = u8"你好,世界!";

语法

折叠表达式

  • 用于变长参数模板的解包,只支持各种运算符(和操作符)
template <typename ...T>
auto SubRight(T... args)
{
	return (args - ...);//右折叠
}

template <typename ...T>
auto SubLeft(T... args)
{
	return (... - args);//左折叠
}

SubLeft(9, 8, 7, 6, 5);//(((9 - 8) - 7) - 6) - 5
SubRight(9, 8, 7, 6, 5);//9 - (8 - (7 - (6 - 5)))

结构化绑定

  • 依然是auto关键字,用一对包含一个或多个变量的中括号,表示结构化绑定
struct test
{
	int a;
	double b;
};
using testList = std::vector<test>
test func(int a, double b)
{
	float x = a * a;
	size_t y = b * b;
	return [x, y];
}
auto [x, y] = fucn(10, 13.14);//x推导为float, y推导为size_t;
for(auto [x, y] : testList)//另一种使用方法

允许非类型模板参数进行常量计算

class a
{
public:
	static int b;
};
template <typename T>
auto func(T b)
{
	return b;
}
auto ret = func<int>(a::b);

条件分支语句初始化

std::vector<int> v = { 1, 2, 3, 5, 4 };
if(auto itr = v.begin(); itr != v.end())
{
	...//switch同样的
}

聚合初始化

  • 在C++17之前,结构体使用大括号初始化需写构造函数,现在不需要了
struct x
{
	int a;
	float b;
};
struct y : x
{
	std::string c;
};

y z = { { 10, 20 }, "hello world" };
y z{ { 10, 20 }, "hello world" };

嵌套命名空间

  • 简化多层命名空间的写法
//传统写法
namespace a
{
	namespace b
	{
		namespace c
		{}
	}
}
//C++17写法
namespace a::b::c
{
}

lambda表达式捕获*this的值

  • 新增拷贝捕获对象,也可以说是只有读权限的对象
struct test
{
	int m_val;
	int func()
	{
		return [*this]{ return this->m_val; };
	}
};

细化表达式的计算顺序

  • 为了支持泛型编程和重载运算符的广泛使用,新特性将计算顺序进行的细化
std::map<int, int> tmp;
//对于std::map的[]运算符重载函数,在使用[]新增key时,std::map就已经插入了一个新的键值对
tmp[0] = tmp.size();//此处不知道插入的是{0, 0}还是{0, 1}

为了解决该情况,新计算顺序规则为:
①后缀表达式从左到右求值。这包括函数调用和成员选择表达式。
②赋值表达式从右向左求值。这包括复合赋值。
③从左到右计算移位操作符的操作数。

模板类的模板参数自动推导

  • 模板实例化时可不用显式指定类型,保证类型可以推导是必要条件
std::piar p(2, 3.14);

auto作为非类型模板参数

  • 当模板参数为非类型时,可用auto自动推导类型
template <auto T>
void func(T t)
{
	std::cout << t;
}
func<100>();//正确
func<int>();//错误

__has_include

  • 判断有没有包含头文件
#if __has_include(<stdio.h>)
printf("has");
#elif __has_include(<iostream>)
std::cout << "has";
#endif

属性

[fallthrough]

  • 用于switch语块内,继续执行下个case
switch(0)
{
case 0:
    ....
    [[fallthrough]];
case 1:
	....
}

[nodiscard]

  • 用于函数声明,若返回值被忽略则出现警告
[[nodiscard]] int func(int a, int b)
{
	return a + b;
}

[maybe_unused]

  • 用于解除对未使用变量或其他引起的编译器警告:[[maybe_unused]] int a;

库函数

std::from_chars & std::to_chars

  • 更方便的处理字符串和数字之间的转换
#include <charconv>
#include <iostream>

int main()
{
	std::string str("1234");
	int val;
	//ec为错误码,详情查看xerrc.h,ptr成员为未转换或非数字的字符
	if(auto[ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), val);
	   ec == std::errc())
	{
		std::cout << val;//1234
	}

	val = 321;
	if(auto[ptr, ec] = std::to_chars(str.data(), str.data() + str.size(), val);
	   ec == std::errc())
	{
		std::cout << str;//3214
	}

	auto format = std::chars_format::general;
	double pi = 0.f;
	str = "3.14";
	if(auto[ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), pi, format);
	   ec == std::errc())
	{
		std::cout << pi;//3.14
	}
	return 0;
}

std::variant

  • 多变的、可变的复合类型
#include <variant>
#include <iostream>

int main()
{
	std::variant<int, std::string> var("123");
    std::variant<int, std::string> v("hello");
    std::cout << v.index();

    v = 123;
    std::cout << v.index();
    v = "321";
    try
    {
            std::string str = std::get<std::string>(v);//str=321
            int i = std::get<0>(v);//抛异常
    }
    catch (std::bad_variant_access& e)
    {
    
    }
	return 0;
}

std::optional

  • 它的内部只有2个状态,要么有值(T类型),要么无值(nullopt)
#include <iostream>
#include <optional>
#include <string>

std::optional<size_t> func(int a)
{
	if(a == 0)
		return 1;
	else if(a > 100)
		return 2;
	return std::nullopt;//可以以此来决定它成功了,其余的则为错误码
}

int main()
{
	std::optional<size_t> opt = std::nullopt;
	opt.has_value();//false
	opt.value();//抛出std::bad_optional_access异常
	opt = func(0);
	opt.has_value();//true
	opt.value();//1
	return 0;
}

std::any

  • 万能变量,类似于py的变量,类型可变,值可变
#include <iostream>
#include <any>
#include <string>

int main()
{
    std::any var;
    var.has_value();//false
    std::cout << var.type().name();//void
    
    var = 1;
    std::cout << var.type().name();//int

    var = 1.f;
    std::cout << var.type().name();//float

    var = "string";
    std::cout << var.type().name();//const char*
    
    return 0;
}

std::apply

  • 将tuple元组解包,并作为函数的传入参数
int func(int a, int b){ return a + b; }
auto fn = [](int a, int b, int c){ return a * b + c; };
std::apply(func, std::pair(2, 3));
std::apply(fn , std::tuple(2, 3, 4));

std::make_from_tuple

  • 解包tuple作为构造函数参数构造对象
struct a
{
	int _a;
	std::string _b;
	a(int a, std::string b) : _a(a), _b(b){}
};

auto tuple = std::make_tuple(10, "hello");
auto a1 = std::make_from_tuple<a>(std::move(tuple ));

std::string_view

  • 这个新的类型出现是为了解决string效率问题,它的内部只会保存一个char*指针,不会申请内存和销毁内存,如果你只需要读这个变量内部的数据而不写入的话,可以使用它
void func(std::string_view str)
{
	std::cout << str;
}
std::string str("hello");
char str1[] = " world";
func(str);
func(str1);

std::as_const

  • 将左值转化为const
int main() 
{
  std::string str("hello world");
  cout << std::is_const<decltype(str)>::value << endl;

  auto str_const = std::as_const(str);
  cout << std::is_const<decltype(str_const)>::value << endl;
  return 0;
}

std::filesystem

#include <iostream>
#include <filesystem>
#include <string>

namespace fs = std::filesystem;

int main()
{
    fs::path file("./1");
    if (!fs::exists(file))
    {
        std::cout << "file is not exist";
    }

    fs::directory_entry entry(file);
    if (entry.status().type() == fs::file_type::directory)
    {
        std::cout << "it's a directory.";
    }

    fs::directory_iterator iter(file);
    for (auto& path : iter)
    {
        std::cout << path.path().filename();
    }
    /*
	"test17.exe""test17.ilk""test17.pdb"
	*/

    getchar();
    return 0;
}

std::shared_mutex

  • 线程锁
class SafeThread
{
public:
	SafeThread() = default;
private:
    mutable std::shared_mutex _mutex;
    size_t _val = 0;
public:
	size_t get()const
	{
		std::shared_lock lock(_mutex);
		return _val;
	}
	void add()
	{
		std::unique_lock lock(_mutex);
		++_val;
	}
	void reset()
	{
		std::unique_lock lock(_mutex);
		_val = 0;
	}
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-13 11:37:20  更:2022-05-13 11:38:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/10 19:25:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码