C++ 新特性 | C++14 常用新特性介绍

目录

1、通用lambda表达式(对lambda表达式的改进)

2、constexpr常量表达式

3、constexpr函数的扩展

4、二进制字面量

5、数组大小自动推导

6、std::make_unique

7、std::exchange

8、std::integer_sequence

9、变长参数模板的扩展


C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C/C++实战进阶(专栏文章已更新390多篇,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.htmlWindows C++ 软件开发从入门到精通(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12695902.htmlVC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++软件分析工具从入门到精通案例集锦(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795开源组件及数据库技术(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12458859.html网络编程与网络问题分享(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_2276111.html       C++14标准在2014年8月18日被C++标准委员会正式批准宣布,同年12月15日正式发布release版本,作为C++11标准的一个较小但重要的补充和改进,它在保持向后兼容性的同时,引入了一系列旨在提高代码简洁性和效率的新特性和增强功能。下面介绍一下C++14的常用新特性。

  • 很多C++开源库会大规模地使用C++11及以上的新特性,比如WebRTC开源库,所以在阅读开源代码时需要了解C++11及以上新特性。我们在日常编码中会用到部分新特性,比如一些新的关键字(auto、nullptr、override、final等)、lambda表达式(匿名函数)、智能指针等。此外,现在很多C++开发岗位在面试时都会问到C++11或以上的新特性方面的内容。所以学习C++11及以上的新特性很有必要!
  • C++新标准引入的诸多新特性,解决了语言上的部分缺陷,使得C++更得加高效灵活!但也使得C++变得更加臃肿复杂,更加难以驾驭!

1、通用lambda表达式(对lambda表达式的改进)

       C++14引入了通用lambda表达式,可以使用auto关键字作为参数类型和返回类型,使得lambda表达式更加灵活。

       通用lambda表达式的语法如下:

[ captures ] ( auto&&... params ) -> decltype(auto) { body }

其中,captures是lambda表达式的捕获列表,params是lambda表达式的参数列表,decltype(auto)表示返回类型会根据body自动推导出来。

       对C++11中的Lambda表达式的改进,主要体现在以下两个方面:

  • 初始化捕获:在C++14中,lambda表达式的捕获列表支持直接初始化捕获的变量,这意味着可以在定义lambda时直接为捕获的变量赋予初始值,而无需在外部提前声明。
  • 泛型Lambda:C++14允许在Lambda表达式中使用auto作为参数类型,这使得Lambda可以更加灵活地处理不同类型的参数,而无需显式指定类型。

       例如,以下是一个使用通用lambda表达式的例子:

#include <iostream>

int main() 
{
    auto sum = [](auto x, auto y) 
    {
        return x + y;
    };
    
    std::cout << sum(2, 3) << std::endl; // 输出 5
    std::cout << sum(1.0, 2.5) << std::endl; // 输出 3.5
    
    return 0;
}

在这个例子中,lambda表达式的参数类型和返回类型都使用了auto关键字,使得它可以接受不同类型的参数,并返回相应的结果。

2、constexpr常量表达式

       C++14中,常量表达式是指在编译时可以计算出结果的表达式,它可以用于声明常量、数组大小、枚举值等。C++14中新增了一些常量表达式的规则:

1)函数可以被声明为常量表达式,只要函数满足以下条件:

a)函数的返回值类型是字面类型(literal type)

b)函数体只包含符合常量表达式要求的语句

2)可以使用if和switch语句,只要它们的条件表达式是常量表达式,并且语句体也是符合常量表达式要求的语句。

3)可以使用循环语句,只要循环次数是常量表达式。

4)可以使用lambda表达式,只要它符合常量表达式的要求。

下面是一个使用常量表达式的例子:

constexpr int factorial(int n) 
{
    return n <= 1 ? 1 : n * factorial(n - 1);
}

int main() 
{
    constexpr int n = 5;
    int arr[factorial(n)]; // 使用常量表达式计算数组大小
    return 0;
}

在上面的例子中,函数factorial被声明为常量表达式,并用于计算数组arr的大小。由于n是一个编译时常量,因此可以在编译时计算出factorial(n)的值,从而确定数组的大小。

打印到控制台上。print函数创建一个std::tuple对象,并使用std::make_index_sequence来创建一个std::index_sequence对象,然后将它们传递给print_helper函数。foo函数使用print函数来打印参数。


       在这里,给大家重点推荐一下我的几个热门畅销专栏,欢迎订阅:(博客主页还有其他专栏,可以去查看)

专栏1:(该精品技术专栏的订阅量已达到500多个,专栏中包含大量项目实战分析案例,有很强的实战参考价值,广受好评!专栏文章持续更新中,预计更新到200篇以上!欢迎订阅!)

C++软件调试与异常排查从入门到精通系列文章汇总icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931

本专栏根据多年C++软件异常排查的项目实践,系统地总结了引发C++软件异常的常见原因以及排查C++软件异常的常用思路与方法,详细讲述了C++软件的调试方法与手段,以图文并茂的方式给出具体的项目问题实战分析实例(很有实战参考价值),带领大家逐步掌握C++软件调试与异常排查的相关技术,适合基础进阶和想做技术提升的相关C++开发人员!

考察一个开发人员的水平,一是看其编码及设计能力,二是要看其软件调试能力!所以软件调试能力(排查软件异常的能力)很重要,必须重视起来!能解决一般人解决不了的问题,既能提升个人能力及价值,也能体现对团队及公司的贡献!

专栏中的文章都是通过项目实战总结出来的,包含大量项目问题实战分析案例,有很强的实战参考价值!专栏文章还在持续更新中,预计文章篇数能更新到200篇以上!

专栏2:  

C++常用软件分析工具从入门到精通案例集锦汇总(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795

常用的C++软件辅助分析工具有SPY++、PE工具、Dependency Walker、GDIView、Process Explorer、Process Monitor、API Monitor、Clumsy、Windbg、IDA Pro等,本专栏详细介绍如何使用这些工具去巧妙地分析和解决日常工作中遇到的问题,很有实战参考价值!

专栏3:(本专栏涵盖了多方面的内容,是当前重点打造的专栏,专栏文章已经更新到390多篇,持续更新中...)

C/C++实战进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html

以多年的开发实战为基础,总结并讲解一些的C/C++基础与项目实战进阶内容,以图文并茂的方式对相关知识点进行详细地展开与阐述!专栏涉及了C/C++领域多个方面的内容,包括C++基础及编程要点(模版泛型编程、STL容器及算法函数的使用等)、C++11及以上新特性(不仅看开源代码会用到,日常编码中也会用到部分新特性,面试时也会涉及到)、常用C++开源库的介绍与使用、代码分享(调用系统API、使用开源库)、常用编程技术(动态库、多线程、多进程、数据库及网络编程等)、软件UI编程(Win32/duilib/QT/MFC)、C++软件调试技术(排查软件异常的手段与方法、分析C++软件异常的基础知识、常用软件分析工具使用、实战问题分析案例等)、设计模式、网络基础知识与网络问题分析进阶内容等。

专栏4:   

VC++常用功能开发汇总(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585

将10多年C++开发实践中常用的功能,以高质量的代码展现出来。这些常用的高质量规范代码,可以直接拿到项目中使用,能有效地解决软件开发过程中遇到的问题。

专栏5: 

Windows C++ 软件开发从入门到精通(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12695902.html

根据多年C++软件开发实践,详细地总结了Windows C++ 应用软件开发相关技术实现细节,分享了大量的实战案例,很有实战参考价值。


3、constexpr函数的扩展

       C++11引入了constexpr函数的概念,这样的函数可以在编译期执行。然而,C++11要求constexpr函数只含有一个将被返回的表达式。C++14放宽了这些限制,允许constexpr函数中使用局部变量、循环和条件语句等,只要最终的结果能够在编译时计算得出即可。       

       C++14中对constexpr函数的扩展主要包括以下几个方面:

1)放宽了对constexpr函数的限制:在C++11中,constexpr函数只能包含一些简单的语句,比如赋值语句和return语句,而在C++14中,constexpr函数可以包含一些复杂的语句,比如if语句和循环语句。

2)允许constexpr函数调用非constexpr函数:在C++11中,constexpr函数只能调用其他constexpr函数,而在C++14中,constexpr函数可以调用非constexpr函数,只要这些函数的返回值可以在编译时确定。

3)允许constexpr函数返回void类型:在C++11中,constexpr函数必须返回一个常量表达式,而在C++14中,constexpr函数可以返回void类型,只要函数体中的语句都是常量表达式。

4)允许constexpr函数有多个参数:在C++11中,constexpr函数只能有一个参数,而在C++14中,constexpr函数可以有多个参数,只要这些参数都是常量表达式。

5)允许constexpr函数有局部变量:在C++11中,constexpr函数不能有局部变量,而在C++14中,constexpr函数可以有局部变量,只要这些变量都是常量表达式。

总的来说,C++14中对constexpr函数的扩展使得这种函数更加灵活和实用,可以用于更多的场景,提高代码的可读性和可维护性。

4、二进制字面量

       C++14引入了二进制字面量,允许程序员使用二进制表示法来表示整数值。二进制字面量以前缀0b或0B开头,后面跟着一串二进制数字。例如,0b111111表示十进制数63。并且允许在数字字面量中使用单引号作为分隔符,以提高代码的可读性。

       以下是一个简单的示例:

#include <iostream>

int main() 
{
    int i = 0b111111;
    std::cout << i << std::endl; // 输出63
    return 0;
}

二进制字面量提供了一种简单而方便的方法来表示位模式,这对于编写低级别的系统代码或进行位运算非常有用。

5、数组大小自动推导

       在C++14中,可以使用auto关键字和初始化列表来实现数组大小的自动推导。具体来说,可以使用以下语法:

auto arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // 自动推导为std::initializer_list<int>

在这个例子中,编译器会自动推导出arr的类型为std::initializer_list< int >,而数组的大小也会自动根据初始化列表的元素个数进行推导。因此,上述代码等价于下面的代码:

int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // 数组大小为10

需要注意的是,这种自动推导方式只适用于静态数组,而对于动态数组来说,还需要使用new运算符手动分配内存。另外,由于std::initializer_list是一个轻量级的容器,因此它的性能可能不如普通数组。

6、std::make_unique

       C++14中的std::make_unique是一个函数模板,用于创建一个std::unique_ptr对象并将其初始化为一个新对象。它接受一个可变参数列表和一个构造函数的参数列表,用于在创建新对象时传递给构造函数。

       make_unique的语法如下:

template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args);

其中,T是要创建的对象的类型,Args是传递给构造函数的参数列表。make_unique返回一个std::unique_ptr对象,该对象拥有指向新对象的所有权。

       使用make_unique可以避免手动创建std::unique_ptr对象并进行new操作,从而避免了内存泄漏和错误的可能性。它还可以提高代码的可读性和简洁性。以下是一个使用make_unique创建一个动态分配的对象的例子:

#include <memory>
#include <iostream>

class TestClass 
{
public:
    TestClass(int value) : m_value(value) 
    {
        std::cout << "TestClass constructor called with value: " << m_value << std::endl;
    }

    ~TestClass() 
    {
        std::cout << "TestClass destructor called with value: " << m_value << std::endl;
    }

private:
    int m_value;
};

int main() {
    auto ptr = std::make_unique<TestClass>(20);
    return 0;
}

在这个例子中,我们使用make_unique创建了一个动态分配的MyClass对象,并将其初始化为值20。当程序退出main函数时,指向该对象的指针ptr将被自动销毁,并调用MyClass的析构函数。

       需要注意的是,make_unique不能用于创建数组,因为std::unique_ptr不支持动态数组。如果需要创建动态数组,应该使用std::vector或std::array。

7、std::exchange

       std::exchange是C++14中引入的一个函数模板,它定义在头文件中。这个函数的作用是交换一个对象的值并返回其旧值。

       std::exchange的函数原型如下:

template<class T, class U = T>
T exchange(T& obj, U&& new_value);

其中,T是要交换值的对象的类型,obj是要交换值的对象的引用,new_value是新值,U是新值的类型。

       这个函数的作用是将obj的值用new_value替换,并返回obj原来的值。这个操作是原子的,所以在多线程环境中使用是安全的。以下是一个使用std::exchange的例子:

#include <iostream>
#include <utility>

int main()
{
    int x = 1;
    int y = std::exchange(x, 2);
    std::cout << "x = " << x << ", y = " << y << std::endl; // 输出x = 2, y = 1
    return 0;
}

在这个例子中,我们使用std::exchange将x的值从1替换成2,并将原来的值1赋给了y。

8、std::integer_sequence

       C++14中的std::integer_sequence是一个模板类,用于创建一个整数序列。它可以用于编写与模板参数数量和类型无关的代码,例如元编程和模板元函数。

       std::integer_sequence有两个模板参数:第一个是整数类型(通常是std::size_t),第二个是整数序列的长度。例如,std::integer_sequence<std::size_t, 3>表示一个包含三个std::size_t类型整数的序列。

       std::make_integer_sequence模板函数可以用来创建一个整数序列。它接受一个整数类型和一个整数序列长度作为参数,并返回一个std::integer_sequence对象。例如,std::make_integer_sequence<std::size_t, 5>将返回一个包含0到4的std::size_t类型整数的序列。

       std::index_sequence是std::integer_sequence的特化版本,其中第一个模板参数固定为std::size_t。它通常用于访问元组中的元素,因为元组中的元素是按照索引顺序存储的。

       使用std::integer_sequence和std::make_integer_sequence可以实现可变参数模板的参数展开,例如:

template<typename... Ts>
void foo(Ts... args)
{
    bar(std::make_index_sequence<sizeof...(Ts)>{}, args...);
}

template<typename... Ts, std::size_t... Is>
void bar(std::index_sequence<Is...>, Ts... args)
{
    // 访问args中的元素,例如:
    int x = std::get<Is>(std::make_tuple(args...));
}

       在上面的例子中,foo函数接受任意数量和类型的参数,并将它们传递给bar函数。bar函数使用std::index_sequence来访问args中的元素。

#include <iostream>
#include <utility>

template<typename... Ts, std::size_t... Is>
void print_helper(const std::tuple<Ts...>& tpl, std::index_sequence<Is...>)
{
    ((std::cout << std::get<Is>(tpl) << ' '), ...);
    std::cout << '\n';
}

template<typename... Ts>
void print(Ts... args)
{
    std::tuple<Ts...> tpl(args...);
    print_helper(tpl, std::make_index_sequence<sizeof...(Ts)>());
}

template<typename... Ts>
void foo(Ts... args)
{
    print(args...);
}

int main()
{
    foo(1, 1.5, "Hello World");  // 输出:1 1.5 Hello World
    return 0;
}

在上面的例子中,print_helper函数使用std::index_sequence来展开std::tuple中的元素,并将它们

9、变长参数模板的扩展

       C++14中引入了变长参数模板的扩展,可以使用类似于函数参数的语法来定义模板参数列表。这个特性被称为“参数包扩展”或“参数模板扩展”。参数模板扩展允许在模板参数列表中使用省略号(…)来表示一个可变数量的模板参数。这些参数被称为“参数包”,可以在模板定义中使用。

       例如,下面的代码定义了一个可变参数模板,用于在编译时计算一组数字的总和:

template<typename... Args>
int sum(Args... args) 
{
    return (args + ...);
}

在这个例子中,省略号表示Args是一个可变数量的模板参数。在函数体中,使用了折叠表达式(fold expression)来计算所有参数的总和。

       使用参数模板扩展可以极大地简化代码,特别是在处理不同数量的参数时。例如,可以定义一个可变参数模板来打印任意数量的值:

template<typename... Args>
void print(Args... args) 
{
    (std::cout << ... << args) << '\n';
}

       在这个例子中,省略号表示Args是一个可变数量的模板参数。在函数体中,使用了折叠表达式来将所有参数输出到标准输出。

  • 21
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
### 支持向量机非线性回归通用MATLAB程序解析 #### 一、概述 本文将详细介绍一个基于MATLAB的支持向量机(SVM)非线性回归的通用程序。该程序采用支持向量机方法来实现数据的非线性回归,并通过不同的核函数设置来适应不同类型的数据分布。此外,该程序还提供了数据预处理的方法,使得用户能够更加方便地应用此程序解决实际问题。 #### 二、核心功能与原理 ##### 1. 支持向量机(SVM) 支持向量机是一种监督学习模型,主要用于分类和回归分析。对于非线性回归任务,SVM通过引入核技巧(kernel trick)将原始低维空间中的非线性问题转换为高维空间中的线性问题,从而实现有效的非线性建模。 ##### 2. 核函数 核函数的选择直接影响到模型的性能。本程序内置了三种常用的核函数: - **线性核函数**:`K(x, y) = x'y` - **多项式核函数**:`K(x, y) = (x'y + 1)^d` - **径向基函数(RBF)**:`K(x, y) = exp(-γ|x - y|^2)` 其中RBF核函数被广泛应用于非线性问题中,因为它可以处理非常复杂的非线性关系。本程序默认使用的是RBF核函数,参数`D`用于控制高斯核函数的宽度。 ##### 3. 数据预处理 虽然程序本身没有直接涉及数据预处理的过程,但在实际应用中,对数据进行适当的预处理是非常重要的。常见的预处理步骤包括归一化、缺失值处理等。 ##### 4. 模型参数 - **Epsilon**: ε-insensitive loss function的ε值,控制回归带宽。 - **C**: 松弛变量的惩罚系数,控制模型复杂度与过拟合的风险之间的平衡。 #### 三、程序实现细节 ##### 1. 函数输入与输出 - **输入**: - `X`: 输入特征矩阵,维度为(n, l),其中n是特征数量,l是样本数量。 - `Y`: 目标值向量,长度为l。 - `Epsilon`: 回归带宽。 - `C`: 松弛变量的惩罚系数。 - `D`: RBF核函数的参数。 - **输出**: - `Alpha1`: 正的拉格朗日乘子向量。 - `Alpha2`: 负的拉格朗日乘子向量。 - `Alpha`: 拉格朗日乘子向量。 - `Flag`: 标记向量,表示每个样本的类型。 - `B`: 偏置项。 ##### 2. 核心代码解析 程序首先计算所有样本间的核矩阵`K`,然后构建二次规划问题并求解得到拉格朗日乘子向量。根据拉格朗日乘子的值确定支持向量,并计算偏置项`B`。 - **核矩阵计算**:采用RBF核函数,通过`exp(-(sum((xi-xj).^2)/D))`计算任意两个样本之间的相似度。 - **二次规划**:构建目标函数和约束条件,使用`quadprog`函数求解最小化问题。 - **支持向量识别**:根据拉格朗日乘子的大小判断每个样本是否为支持向量,并据此计算偏置项`B`。 #### 四、程序扩展与优化 - **多核函数支持**:可以通过增加更多的核函数选项,提高程序的灵活性。 - **自动调参**:实现参数自动选择的功能,例如通过交叉验证选择最优的`Epsilon`和`C`值。 - **并行计算**:利用MATLAB的并行计算工具箱加速计算过程,特别是当样本量很大时。 #### 五、应用场景 该程序适用于需要进行非线性回归预测的场景,如经济预测、天气预报等领域。通过调整核函数和参数,可以有效应对各种类型的非线性问题。 ### 总结 本程序提供了一个支持向量机非线性回归的完整实现框架,通过灵活的核函数设置和参数调整,能够有效地处理非线性问题。对于需要进行回归预测的应用场景,这是一个非常实用且强大的工具。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dvlinker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值