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的新特征

结构化绑定

结构化绑定就是将指定的名称和初始化器的子对象或元素绑定。
与引用一样,结构化绑定是现有对象的别名。与引用不同的是,结构化绑定不必是引用类型。

下面展示一些 内联代码片

attr(optional) cv-auto ref-qualifier(optional) [ identifier-list ] = expression ;	   (1)	
attr(optional) cv-auto ref-qualifier(optional) [ identifier-list ] { expression } ;	(2)	
attr(optional) cv-auto ref-qualifier(optional) [ identifier-list ] ( expression ) ;	(3)	

attr任意数量属性的序列
cv-auto可能是 cv 限定的类型说明符是,auto,也可能包括存储类说明符,static 或 thread_local
ref-qualifier& 或者 &&
identifier-list此说明引入的,逗号分隔的标识符列表
expression是一个表达式,该表达式在顶层,没有逗号运算符(语法上,是赋值表达式),并且具有数组或非联合类类型。如果表达式引用标识符列表中的任何名称,则说明格式是错误的。

绑定数组

标识符列表中的每个标识符都成为一个左值的名称,该左值引用数组的相应元素。标识符的数量必须等于数组元素的数量。
每个标识符的引用类型是数组元素类型。如果数组类型 E 是 cv 限定的,那么它的元素类型也是如此。

例子

int a[2] = {1,2};
 
auto [x,y] = a; // creates e[2], copies a into e, then x refers to e[0], y refers to e[1]
auto& [xr, yr] = a; // xr refers to a[0], yr refers to a[1]

绑定一个tuple类型

表达式 std::tuple_size::value 必须是良定义的整数常量表达式,并且,标识符的数量必须等于 std::tuple_size::value。
对于每个标识符,引用一个变量,该变量的类型是,引入一个类型为,std::tuple_element<i, E>::type 的引用。如果其对应的初始值设定项是左值,则为左值引用,否则为右值引用。第 i 个变量的初始化器是

  • e.get(),如果通过类成员访问查找在 E 范围内查找标识符,get 发现至少一个说明是函数模板,其第一个模板参数是非类型参数
  • 否则,get(e),其中 get 仅通过依赖于参数的查找来查找,忽略非 ADL 查找。

在这些初始化器表达式中,如果实体 e 的类型是左值引用,则 e 是左值(仅当 ref 限定符是 & 或 &&, 并且初始化器表达式是左值时,才会发生这种情况),否则是 xvalue(这有效地执行一种完美转发),i 是 std::size_t prvalue,并且 <i> 总是被解释为模板参数列表。
该变量具有与 e 相同的存储持续时间。
该标识符然后成为一个左值的名称,该左值引用绑定到所述变量的对象。
第 i 个标识符的引用类型是 std::tuple_element<i, E>::type。

例子

float x{1.0};
char  y{‘c'};
int   z{5};
 
std::tuple<float&,char&&,int> tpl(x,std::move(y),z);

const auto& [a,b,c] = tpl;
// a 命名结构化绑定,它是x的引用; decltype(a) is float&
// b 命名结构化绑定,它是y的引用; decltype(b) is char&&
// c 命名结构化绑定它是tpl的第三个元素的引用; decltype(c) is const int

绑定数据成员

  • E 的每个非静态数据成员必须是 E 的直接成员或 E 的相同基类
  • 并且在命名为 e.name 时,必须在结构化绑定的上下文中是良定义的。
  • E不能有匿名union成员。
  • 标识符的数量必须等于非静态数据成员的数量。

标识符列表中的每个标识符都成为一个左值的名称,按说明顺序,该左值引用 e 的下一个成员(支持位字段);左值的类型是 e.m_i 的类型,其中 m_i 指的是第 i 个成员。
第 i 个标识符的引用类型,如果不是引用类型,则为 e.m_i 的类型,否则为 m_i 的说明类型。

例子

#include <iostream>
struct S {
    mutable int x1 : 2;
    volatile double y1;
};
S f() { return S{1, 2.3}; }
 
int main() {
    const auto [x, y] = f();  // x is an int lvalue identifying the 2-bit bit field
                              // y is a const volatile double lvalue
    std::cout << x << ' ' << y << '\n';  // 1 2.3
    x = -2;   // OK
//  y = -2.;  // Error: y is const-qualified
    std::cout << x << ' ' << y << '\n';  // -2 2.3
}

if/switch 的初始化语句

if语句初始化

C++17 扩展了现有 if 语句的语法。可以在 if 语句本身中提供初始条件。这种新语法称为“带有初始化程序的 if 语句”。此增强功能简化了常见的代码模式,并帮助用户保持范围紧凑。这避免了范围外的变量泄漏。

例子

#include <iostream>
#include <cstdlib>
using namespace std;
int main() {
   srand(time(NULL));
   // C++17 if statement with initializer
   if (int random_num = rand(); random_num % 2 == 0) {
      cout << random_num << " is an even number\n";
   } else {
      cout << random_num << " is an odd number\n";
   }
   return 0;
}

if与结构化绑定结合

当与结构化绑定结合使用时,带有初始化器的 if 的用处变得更加明显。
使用结构化绑定将 std::map::insert 的 std::pair 返回值解包为两个单独的变量,it(迭代器)和 Inserted(指示插入是否成功的布尔值)。
然后我们可以通过检查insert,来检查if语句中的插入是否成功。

例子

int main()
{
    std::map<std::string, int> map;
    map["hello"] = 1;
    map["world"] = 2;

    // intitialize the condition we want to check from within the if statement
    if (auto [it, inserted] = map.insert({ "hello", 3 }); !inserted)
        std::cout << "hello already exists with value " << it->second << "\n";

    // ret has not leaked, so we can use that for this conditional check too
    if (auto [it, inserted] = map.insert({ "foo", 4 }); !inserted)
        std::cout << "foo already exists with value " << it->second << "\n";

    return 0;
}

switch语句初始化

与 if 语句一样,我们现在可以在 switch 语句中创建变量。

例子

enum Result
{
    SUCCESS,
    ABORTED
};

std::pair<size_t /* bytes */, Result> read_message()
{
    return { 100, SUCCESS };
}

int main()
{
    switch (auto res = read_message(); res.second)
    {
        case SUCCESS:
            std::cout << "successfully wrote " << res.first << " bytes\n";
            break;
        case ABORTED:
            std::cout << "operation aborted before completion\n";
            break;
    }
    return 0;
}

inline变量

constexpr if

例子

#include <iostream>
#include <string>

struct S 
{
    int n;
    std::string s;
    float d;
};

template <std::size_t I>
auto& get(S& s)
{
    if constexpr (I == 0)
        return s.n;
    else if constexpr (I == 1)
        return s.s;
    else if constexpr (I == 2)
        return s.d;
}

int main()
{
	S obj { 0, "hello", 10.0f };
    std::cout << get<0>(obj) << endl;
    std::cout << get<1>(obj) << endl;
}

折叠表达式

左结合二元运算符

右结合二元运算符

类模板的模板参数推导

为了实例化一个类模板,必须知道每个模板参数,但这不是说,必须指定每个模板参数。根据上下文,编译器可以从初始器的类型,推导出模板参数。

任何指定变量初始化和变量模板的说明

下面展示一些 内联代码片

// A code block
var foo = 'bar';
std::pair p(2, 4.5);     // 推导出 std::pair<int, double> p(2, 4.5);
std::tuple t(4, 3, 2.5); // auto t = std::make_tuple(4, 3, 2.5);

new表达式

例子

template<class T> struct A
{
    A(T, T);
};
auto y = new A{1, 2}; // 分配的类型是 A<int>
auto z = new A{1.5}; // 分配的类型是 A<double>

函数式式的cast表达式

内联代码片

auto lck = std::lock_guard(mtx);     // deduces to std::lock_guard<std::mutex>
std::copy_n(vi1, 3,
    std::back_insert_iterator(vi2)); // deduces to std::back_insert_iterator<T>,
                                     // where T is the type of the container vi2
std::for_each(vi.begin(), vi.end(),
    Foo([&](int i) {...}));          // deduces to Foo<T>,
                                     // where T is the unique lambda type

auto 说明非类型模板参数

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 20:30:29  更:2022-03-21 20:33:16 
 
开发: 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年11日历 -2024/11/24 2:40:13-

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