【C++14新特性】

函数返回值类型推导

#include <iostream>

using namespace std;

// C++14写法
template<typename T, typename U>
auto func1(T t, U u) {
    return t + u;
}
// C++11写法
template<typename T, typename U>
auto func2(T t, U u)->decltype(t + u) {
    return t + u;
}

int main() {
    cout << func1(4, 5) << endl;
    cout << func2(5.5, 6.6) << endl;
    return 0;
}

C++11时,推断函数返回值类型需要将返回值类型后置并借助decltype关键词,比较麻烦。对此,C++14拓展了auto的范围,可以直接推到函数返回值类型。但是,应用auto推导返回值类型也有一些限制。
一:函数内如果有多个return语句,它们必须返回相同的类型,否则编译失败
二:如果return语句返回初始化列表,返回值类型推导也会失败
tips:初始化列表没有类型,因此auto无法进行类型推导
三: 如果函数是虚函数,不能使用返回值类型推导
四:返回类型推导可以用在递归函数中,但是递归调用必须以至少一个返回语句作为先导,以便编译器推导出返回类型

auto sum(int i) {
    if (i == 1)
        return i;              // return int
    else
        return sum(i - 1) + i; // ok
}

泛型lambda

#include <iostream>

using namespace std;

// C++14写法
auto func1 = [](auto a) { return a; };

// C++11写法
auto func2 = [](int a) { return a; };

int main() {
	cout << func1(1.1f) << endl;
	cout << func2(2) << endl;
}

在C++11中,lambda表达式参数需要使用具体的类型声明,而C++14可以使用auto。这样,lambda表达式也可以用于泛型编程。

lambda初始化表使用表达式和move

C++11 的 lambda 函数通过值拷贝(by copy)或引用(by reference)捕获(capture)已在外层作用域声明的变量。这意味着 lambda 的值成员不可以是 move-only 的类型。C++14允许被捕获的成员用任意的表达式初始化。这既允许了 capture by value-move,也允许了任意声明 lambda 的成员,而不需要外层作用域有一个具有相应名字的变量。

#include <iostream>

using namespace std;

int main() {
	auto func = [val = 3]{return val;};
	auto ptr = std::make_unique<int>(10); //See below for std::make_unique
	auto lambda = [ptr = std::move(ptr)]{ return *ptr; };
	cout << func() << endl;
	cout << lambda() << endl;
}

运行结果:

3
10

在这里插入图片描述

decltype(auto)

在C++11中,我们使用auto和decltype都可以推断类型。二者的主要区别在于auto推断会丢失引用类型信息,而decltype推断保留引用类型信息。auto和decltype的用法不同,auto直接用于定义变量,decltype只生成类型。decltype用途广,可以推导任意表达式的类型,如果该表达式长度过长,就非常不方便了。于是C++14推出了decltype(auto),用法如下:

	int x = 1, y = 2, c = 3, d = 4;
	float e = 3.0;
	// C++14写法
	decltype(auto)z1 = x + y + c + d + e; 
	// C++11写法
	decltype(x + y + c + d + e)z2 = x + y + c + d + e;

decltype(auto)中的auto其实就是一个占位符,内容就是右侧的表达式。

拓展constexpr关键字

放宽了对constexpr函数的限制:在 C++11 中,constexpr 函数的函数体只能有using 指令、typedef 语句、static_assert 断言、空语句,只能有一条return 语句,并且该语句必须是常量表达式。而在 C++14 中,constexpr 函数可以包含多条语句,可以有条件语句(如 if)和循环语句(如 for、while),只要在编译时能够被求值为常量表达式即可。例如:

constexpr int factorial(int n) {
    int result = 1;
    for (int i = 1; i <= n; ++i) {
        result *= i;
    }
    return result;
}

constexpr int result = factorial(5);  // 在编译时计算出结果 120

变量模板

template<class T>
constexpr T pi = T(3.1415926535897932385L); // variable template

int main()
{
    std::cout << pi<double> << std::endl;
    std::cout << pi<float> << std::endl;
    std::cout << pi<int> << std::endl;
    return 0;
}

// 输出结果
3.14159
3.14159
3

二进制字面值

二进制字面值可以使用0b或者0B开头来表示

int i = 0b0100010001;  // 273
int i = 0B0100010001;  // 273,大写B

数值分位符

数位分隔符不影响数值,只是有了跟好的可读性。

long k = 1'234'567'890

通过类型寻址元组

C++11 引入的 std::tuple 类型允许不同类型的值的聚合体用编译期整型常数索引。C++14还允许使用类型代替常数索引,从多元组中获取对象。若多元组含有多于一个这个类型的对象,将会产生一个编译错误:

tuple<string, string, int> t("foo", "bar", 7);
int i = get<int>(t); // i == 7
int j = get<2>(t); // Same as before: j == 7
string s = get<string>(t); //Compiler error due to ambiguity

make unique

std::make_unique 可以像 std::make_shared 一样使用,用于产生 std::unique_ptr 对象

std::unique_ptr<int> ptr = std::make_unique<int>(42);

std::exchange

#include <iostream>
#include <vector>

using namespace std;

int main() {
	vector<int> v1 { 1,2,3,4 };
	vector<int> v2 { 2,2,2,2 };
	v2 = exchange(v1, v2);
}

可以看下exchange的实现:

template<class T, class U = T>
constexpr T exchange(T& obj, U&& new_value) {
    T old_value = std::move(obj);
    obj = std::forward<U>(new_value);
    return old_value;
}

std::exchange和std::swap作用相同,只是std::exchange实现了完美转发。

标准自定义字面量

C++11 增加了自定义字面量(user-defined literals)的特性,使用户能够定义新的字面量后缀,但标准库并没有对这一特性加以利用。C++14 标准库定义了以下字面量后缀:
 “s”,用于创建各种 std::basic_string 类型。
 “h”、“min”、“s”、“ms”、“us”、“ns”,用于创建相应的 std::chrono::duration 时间间隔。

using namespace std::literals;
std::string str = "hello world"s;
std::chrono::seconds dur = 60s;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值