目录

一、泛型Lambda

1.类型推导

2.通用容器打印

3.通用查找函数

4.配合完美转发forward

5.编译器实现Lambda泛型原理

二、Lambda初始化捕获

1.支持移动语义

2.支持更复杂的初始化逻辑

三、decltype(auto)

四、常量表达式constexpr增强

五、返回类型推导

六、变量模板


C++14主要在C++11的基础上进行了一些改进和增强,这些新特性提高了代码的简洁性、可读性和表达能力。

一、泛型Lambda

在C++11中Lambda表达式的参数必须明确类型,而C++14允许使用auto来作为参数类型,实现泛型Lambda。

1.类型推导

auto add_lambda = [](const auto& x, const auto& y) {
		return x + y;
	};
	cout << add_lambda(2, 3) << endl; //5
	cout << add_lambda(3, 3.3) << endl; //6.3
  • 关于auto:auto自动推导类型时会自动剔除掉引用和const属性。

2.通用容器打印

auto print_lambda = [](const auto& container) {
		for (const auto& item : container) {
			cout << item << " ";
		}
	};
	list<string> coler = { "Green","Red","Blue" };
	print_lambda(coler); // 输出:Green Red Blue

3.通用查找函数

auto find_lambda = [](const auto& container, const auto& value) {
		return find(begin(container), end(container), value)
			!= end(container);
	};
	vector<string> fruits = { "apple","orange","banana" };
	cout << find_lambda(fruits, "orange") << endl; //1

4.配合完美转发forward

class MyClass
{
public:
	MyClass(int a, string str)
		:_a(a)
		,_str(str)
	{}
	void print()
	{
		cout << _a << " " << _str << endl;
	}
private:
	int _a;
	string _str;
};

int main()
{
	auto forward_lambda = [](auto&& ... args) {
		return make_unique<MyClass>(std::forward<decltype(args)>(args)...);
	};
	auto smartPtr = forward_lambda(3, "Lambda");
	smartPtr->print(); //3 Lambda
    return 0;
}

5.编译器实现Lambda泛型原理

//当我们写:
	auto lambda = [](auto x, auto y) {
		return x * y;
	};

	//编译器会生成类似这样的代码:
	class CompilerGeneratedName
	{
		template<class T1,class T2>
		auto operator()(T1 x, T2 y) const {
			return x * y;
		}
	};
  • lambada表达式相较于普通函数具有储存额外捕获变量的好处,在需要对多变量操作的情况下比较方便直接捕获需要操作的变量即可,其实lambda表达式在运行时编译器会将其当作一个匿名类型的类对象,内部的成员变量就是其捕获的变量,类内部有一个operator()运算符重载函数,我们调用Lambda对象时编译器其实就会调用operator()运算符重载函数

二、Lambda初始化捕获

1.支持移动语义

  • 解决只移动类型的捕获问题,例如智能指针unique_ptr类型的对象不能进行拷贝构造,只能进行移动语义,此时用C++11中的值或引用捕获则无法正确的捕获。除此之外还可以避免不必要的拷贝。
	unique_ptr<int> smart_ptr = make_unique<int>(3);

	//error:unique_ptr不可拷贝
	auto lambda = [ptr]() {/* ... */};

	//必须使用std::move,但这样会使外部的smart_ptr无效但可使用
	auto lambda1 = [ptr1 = std::move(smart_ptr)](){/* ... */ };

2.支持更复杂的初始化逻辑

	auto getValue = []() { return 100; };
	auto factory = [num = getValue()](const auto& x){
		return[calculated = num * x, squared = num * num](){
			return calculated + squared;
		};
	};
	auto lambda = factory(1);

三、decltype(auto)

decltype(auto)既包含了auto的简洁性,同时也保留了decltype的精确类型推导(包含引用和const属性)。

	int x = 1;
	auto lambda = [&x]()->const int& {
		return x;
	};
	decltype(auto) ret = lambda();
	++ret; //error 因为ret的类型被精确推到为const int&

四、常量表达式constexpr增强

C++放宽了对constexpr函数的限制:允许局部变量、允许循环(while、for)、允许简单的if-else。

可以在编译器执行更复杂的运算,提升运行期性能。

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

int main()
{
	//编译时断言
	static_assert(factorial(3) == 6, "Factorial Error");
    return 0;
}
  • static_assert(常量表达式,错误信息),编译时检查零运行时开销,用于模板约束、类型检查、常量验证。

五、返回类型推导

在函数声明中可以使用auto让编译器自动推导返回类型,前提是所有返回类型一致或可隐式转换。

auto add(int a, int b) {
    return a + b;  // 推导为 int
}

auto concat(const std::string& a, const std::string& b) {
    return a + b;  // 推导为 std::string
}

六、变量模板

变量模板是一种新的模板机制,它允许定义带有模板参数的变量。对传统获的函数模板和类模板的补充,使得可以为某种类型或一组类型定义一个可重用的常量或变量,通常是编译常量(尤其是用constexpr)。

//基本语法
template <typename T>
constexpr T variable_name = value;

//带有多个模板参数
template <typename T, int N>
constexpr T array_size = N;

简单应用:

template <typename T,int N = 1>
constexpr T array_size = N;
int main()
{
	cout << array_size<int> << endl; //1
	cout << array_size<int, 6> << endl; //6
	int n = array_size<int>;
	cout << n << endl; //1
    return 0;
}
//定义一个变量模板,表示某个类型的推荐缓冲区大小
template <typename T,size_t N = 1024>
constexpr size_t buffer_size = N * sizeof(T);
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐