新特性之C++17

2024-07-10 1759阅读

目录

u8字符字面量

新特性之C++17
(图片来源网络,侵删)

noexcept作为类型系统的一部分

Lambda表达式捕获*this

constexpr新特性

编译期的if constexpr语句

constexpr的Lambda表达式

变量新特性

inline变量

结构化绑定

if和switch语句中的初始化器

强制的复制省略(返回值优化)

临时物质化

模板新特性

折叠表达式(…)

类模板实参推导

auto占位的非类型模板形参

u8字符字面量

C++17 引入了u8字符字面量,用于表示 UTF-8 编码的字符串。

auto str = u8"Hello, 世界";

noexcept作为类型系统的一部分

noexcept是 C++11 引入的一个关键字,用于改善C++中异常处理的性能和可用性。noexcept指定的函数保证不会抛出异常,这使得编译器有机会进行优化,同时也为程序员提供了一个清晰的工具来指明哪些函数是安全的,即不会因为异常而失败。
C++17对其改动主要如下:

  1. 更广泛的使用

C++17 标准库在很多已有的函数中增加了noexcept说明。这是因为对异常安全性有更高的要求和对性能优化的关注。比如,在移动语义和智能指针等方面,更频繁地看到noexcept的使用。

  1. 推导规则

C++17 引入了新的推导指南,使得noexcept能够在模板和自动类型推导中得到更好的处理。这包括在模板函数和自动返回类型中,noexcept的状态可以被推导出来。例如,一个模板函数可以根据其模板参数的操作是否不抛出异常,来决定自身是否声明为noexcept。

  1. 移动操作的默认noexcept

在 C++11 和 C++14 中,移动构造函数和移动赋值操作不会自动被推断为noexcept,而在 C++17 中,如果一个类的所有成员和基类的移动构造函数和移动赋值操作都是noexcept的,那么这个类的移动操作也会被推断为noexcept。这改善了容器(如 std::vector)在元素类型是可移动但不抛出异常时的性能,因为容器可以安全地进行更优化的内存操作,如使用realloc而不是手动复制。

  1. 对std::swap的优化

C++17 中,std::swap在可能的情况下使用noexcept来确保不抛出异常,这对于某些类型来说,特别是在模板编程中,可以提高效率和安全性。

Lambda表达式捕获*this

C++17的Lambda引入捕获*this,使得可以捕获当前对象的常量副本,相当于是以值捕获的形式捕获了this指向的对象,并且赋予const属性。

class A
{
    int a = 1;
public:
    void printCopyA()
    {
        auto lambda = [*this] {
            a++; // error C3490: 由于正在通过常量对象访问“a”,因此无法对其进行修改
            std::cout 
        auto lambda = [&] {
            a++;
            std::cout 
    A a;
    a.printA();
    a.printCopyA();
}

    if constexpr (std::is_integral_v
        std::cout 
        std::cout 
        std::cout 
    process(10);    // 输出:Integral type with value: 10
    process(3.14);  // 输出:Floating-point type with value: 3.14
    process("Hello");  // 输出:Other type
}

    if constexpr (std::is_integral_v
        std::cout 
        std::cout 
        nonExistentFunc(value); // 不会被编译
        std::cout 
    process(10);    // 输出:Integral type with value: 10
    process(3.14);  // 输出:Floating-point type with value: 3.14
}
 return a + b; };
static_assert(add(2, 3) == 5);

    return {42, 3.14, "Hello"};
}
int main() {
    auto [a, b, c] = getTuple();
    std::cout 
    int x, y;
};
int main() {
    Point p{10, 20};
    auto [x, y] = p;
    std::cout 
    int arr[] = {1, 2, 3};
    auto [a, b, c] = arr;
    std::cout 
    std::map{"Alice", 5}, {"Bob", 10}};
    if (auto it = myMap.find("Alice"); it != myMap.end()) {
        std::cout 
        std::cout 
    std::vector10, 20, 30, 40};
    switch (auto i = numbers.size(); i) {
        case 4:
            std::cout 
public:
    std::vector
        std::cout 
        std::cout 
        std::cout 
    BigObject obj;
    obj.data.resize(1000);  // 假设是一个资源密集型操作
    return obj;
}
int main() {
    BigObject myObj = createBigObject();
    // 应该看不到复制或移动构造函数的调用信息
    return 0;
}

    int value;
    A(int v) : value(v) { std::cout  std::cout 
    return A(5); // 返回 prvalue
}
void takeA(A a) {
    std::cout 
    const A& aRef = A(10); // prvalue 物质化为临时对象,引用绑定到它
    takeA(A(20)); // prvalue 物质化为临时对象,传递给函数
    A myA = getA(); // prvalue 物质化过程
    return 0;
}

    return (args + ... + std::string(""));  // 一元右折叠
}
int main() {
    std::cout 
    return (std::string("") + ... + args);  // 一元左折叠
}
int main() {
    std::cout 
    return (args + ... + init); // 二元右折叠
}
int main() {
    std::cout 
    return (init + ... + args); // 二元左折叠
}
int main() {
    std::cout 1, 2, 3};
std::pair1, 3.14};
1, 2, 3};  // 推导为 std::vector1, 3.14};    // 推导为 std::pair
};
int main()
{
    std::vector1, 2, 3};
    // 使用例子
    Constant
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]