C++14新特性_第一章C++语言特性_Lambda初始化捕获,decltype(auto)

本文继续介绍C++14新特性,Lambda初始化捕获和decltype(auto)。

文章目录

  • [第一章 C++14语言特性](#第一章 C++14语言特性)
    • [1.3 Lambda初始化捕获](#1.3 Lambda初始化捕获)
      • [1.3.1 Lambda捕获列表语法](#1.3.1 Lambda捕获列表语法)
      • [1.3.2 举例](#1.3.2 举例)
      • [1.3.3 总结](#1.3.3 总结)
    • [1.4 decltype(auto)](#1.4 decltype(auto))

第一章 C++14语言特性

1.3 Lambda初始化捕获

在C++11中,使用Lambda表达式捕获外部变量时,只能捕获左值、拷贝或引用返回方式捕获外部变量。但是,如果在Lambda表达式中访问一个"只可移动,不可拷贝"的对象时,就犯难了。

假如传递一个 std::unique_ptr指针,如果按值传递,编译报错,因为智能指针禁止拷贝;如果按照引用传递,假如这个Lambda在一个线程中处理,处理时间较长,在外边释放后,Lambda表达式中的智能指针出现了悬空引用,导致程序崩溃。

C++11可以在Lambda表达式中使用引用转移资源,但是又需要定义一个变量,这不直接,C++14可以完美解决这个问题。

1.3.1 Lambda捕获列表语法

为了解决这样的问题,C++14引入了捕获列表,可以直接在[ ] 中定义新变量,并进行初始化。

语法格式:

cpp 复制代码
[ 变量名 = 表达式 ] (参数列表) { ... }
	这个"变量名"就是在Lambda内部可以使用的变量的名字。

1.3.2 举例

示例1:通过初始化捕获,将外部资源move到lambda中。

cpp 复制代码
    void test()
    {
		auto ptr = std::make_unique<int>(42);   

		// C++14,使用初始化捕获将 ptr 移动到 lambda 内部
        auto lambda = [p = std::move(ptr)]() 
        {
            std::cout << "Value: " << *p << std::endl;
		};

		lambda();  // 输出: Value: 42

		// 查看 ptr 是否为空,证明所有权已转移
        if (!ptr)
        {
            std::cout << "ptr is null after move." << std::endl;
        }
        // ptr is null after move.
    }

示例2:直接初始化新变量

cpp 复制代码
    void test()
    {
        auto generator = [index = 22]() 
        {
				cout << "Index: " << index << endl;
		};

		generator();  // 输出: Index: 22
    }

示例3:避免不必要的拷贝

cpp 复制代码
std::vector<int> huge_data(10000);

// C++11: [huge_data] 会导致一次昂贵的拷贝
// C++14: [data = std::move(huge_data)] 零拷贝,直接移动
auto process = [data = std::move(huge_data)]() {
    std::cout << "Data size: " << data.size() << std::endl;
};

1.3.3 总结

总结C++14的初始化捕获,它就是对C++11Lambda功能上的扩充,是一次"升级",这使得Lambda更好用了。

1.4 decltype(auto)

C++11中的auto可以推导数据类型,decltype擅长推导类型时,不丢失const和引用属性。

C++14中引入了decltype(auto),将这两种推导方式合二为一。

众所周知,auto会丢失引用和const属性,比如:

cpp 复制代码
int x = 10;
int& ref = x;

auto a = ref; // a 是 int,不是 int&!发生了拷贝。

C++14中,可以使用 decltype(auto)方式,避免丢失引用。

cpp 复制代码
int x = 10;
int& y = x;

// auto: 忽略引用
auto a = y;            // a 是 int

// decltype(auto): 保留引用
decltype(auto) b = y;  // b 是 int&

// 【注意】括号的魔法
// (x) 是一个表达式,decltype((x)) 是 int&
decltype(auto) c = (x); // c 是 int&,绑定到 x

例子2:在泛型编程中,实现函数返回值完美转发。

cpp 复制代码
int g_val = 10;

// 情况 A: 普通 auto
// 丢失引用,返回的是 g_val 的拷贝
auto get_val_copy() { return g_val; } 

// 情况 B: auto&
// 强制返回引用,但如果函数里 return 1; 就会报错(不能绑定到右值)
auto& get_val_ref() { return g_val; }

// 情况 C: decltype(auto)
// 完美!如果表达式是左值,就推导为引用;如果是右值,就推导为值。
decltype(auto) get_val_perfect() {
    return g_val; // 推导为 int&,因为 g_val 是左值
}

decltype(auto) get_num_perfect() {
    return 100;   // 推导为 int,因为 100 是右值
}
相关推荐
不会c嘎嘎1 小时前
【C++】深入理解多态:从用法到原理
开发语言·c++
REDcker1 小时前
软件开发者需要关注CPU指令集差异吗?
linux·c++·操作系统·c·cpu·指令集·加密算法
不知所云,1 小时前
5. SDL3 库项目引入
c++·sdl3
C++ 老炮儿的技术栈2 小时前
用密码学安全随机数生成256位密钥
c语言·开发语言·c++·windows·安全·密码学·visual studio
nianniannnn2 小时前
Eigen 矩阵操作笔记
c++·笔记·线性代数·矩阵
adfass2 小时前
桌面挂件时钟/多功能时钟C++
开发语言·c++·算法
全栈视界师2 小时前
《机器人实践开发②:Foxglove 嵌入式移植 + CMake 集成》
c++·机器人·数据可视化
繁华似锦respect3 小时前
Linux-内核核心组成部分
linux·c++
不知所云,3 小时前
2.windows c/c++ 编译器安装, mingw和clang
c语言·c++·windows·mingw·clang·c编译器