C++Cherno 学习笔记day15 [57]-[60] 静态数组、函数指针、lambda、using namespace std

发布于:2025-04-05 ⋅ 阅读:(14) ⋅ 点赞:(0)

一、C++的静态数组(std::array)

#include <iostream>
#include <array>

int main()
{
	std::array<int, 5> data;
	data[0] = 2;
	data[4] = 1;

	std::array<int, 5> dataOld;
	dataOld[0] = 0;

	std::cin.get();
}

二、C++的函数指针

原始函数指针(raw funtion pointer)
函数指针,是将一个函数赋值给一个变量的方法

函数指针是一种指向函数的指针变量,允许在运行时动态选择并调用函数。
它是实现回调机制、策略模式和动态行为扩展的基础工具。
尽管现代 C++ 提供了更安全的替代方案(如 std::function 和 Lambda 表达式),理解函数指针仍对底层编程和兼容 C 代码至关重要。

在这里插入图片描述

可以用auto/ typedef/ using来使用函数指针

#include <iostream>

void HelloWorld()
{
	std::cout << "Hello World!" << std::endl;
}

int main()
{
	HelloWorld();

	std::cin.get();
}

在这里插入图片描述

#include <iostream>

void HelloWorld()
{
	std::cout << "Hello World!" << std::endl;
}

int main()
{
// 使用auto
	auto function = HelloWorld;

	function();
	function();

	std::cin.get();
}

在这里插入图片描述

#include <iostream>

void HelloWorld(int a)
{
	std::cout << "Hello World! Value:" << a << std::endl;
}

int main()
{
	/*void(*function)();
	auto function = HelloWorld;*/
	// 使用typedef
	typedef void(*HelloWorldFunction)(int);
	HelloWorldFunction function = HelloWorld;

	function(8);

	std::cin.get();
}

在这里插入图片描述

#include <iostream>
#include <vector>

void PrintValue(int value)
{
	std::cout << "Value:" << value << std::endl;
}
void ForEach(const std::vector<int>& values, void(*func)(int))
{
	for (int value : values)
		func(value);
}
	
int main()
{
	std::vector<int> values = { 1, 5, 4, 2, 3 };
	// ForEach(values, PrintValue);
	// []叫做 捕获方式,如何传入传出参数
	ForEach(values, [](int value) { std::cout << "Value:" << value << std::endl; });

	std::cin.get();
}

在这里插入图片描述
在这里插入图片描述
优先使用 std::function 或 Lambda 以实现更安全的回调。

仅在需要兼容 C 或极致性能时使用函数指针。

避免强制转换函数指针类型(除非明确知晓风险)。

三、C++的lambda

本质是一种匿名函数的方式
像快速的一次性函数,展示运行的代码
只要有一个函数指针,就可以在C++里使用lambda 捕获上下文变量

lambda是我们不需要通过函数定义,就可以定义一个函数的方法
用法:在设置函数指针指向函数的任何地方,都可以将它设置为lambda
查看lambda捕获值

// 核心结构
[捕获列表] (参数列表) mutable(可选) 异常属性(可选) -> 返回类型(可选) {
    // 函数体
}

auto sum = [](int a, int b) -> int { 
    return a + b; 
};
cout << sum(3, 5); // 输出 8

通过值传递= 或 引用传递&捕获变量

非捕获lambda可以隐式转换为函数指针,而有捕获lambda不可以。
在这里插入图片描述
mutable修饰符
constexpr修饰符

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

void ForEach(const std::vector<int>& values, const std::function<void(int)>& func)
{
	for (int value : values)
		func(value);
}
	
int main()
{
	std::vector<int> values = { 1, 5, 4, 2, 3 };
	// 返回一个迭代器
	auto it = std::find_if(values.begin(), values.end(), [](int value) { return value > 3; });
	std::cout << *it << std::endl;

	int a = 5;
	auto lambda = [=](int value) { std::cout << "Value:" << value << " " << a << std::endl; };
	
	ForEach(values, lambda);
	std::cin.get();
}

在这里插入图片描述

在这里插入图片描述
总结

Lambda 表达式是现代 C++ 中提升代码表达力的利器,尤其适合以下场景:

短小的一次性逻辑(如 STL 算法中的谓词)。

需要捕获上下文的闭包(如异步回调、状态保存)。

替代传统的函数对象(减少样板代码)。

牢记原则:

慎用引用捕获,避免悬空引用。

优先使用显式捕获列表。

在性能关键路径考虑内联优化可能性。

四、为什么不使用using namespace std

using namespace 命名空间

// ctrl+H 替换

帕斯卡命名法
(每个单词首字母大写,中间不能有空格或下划线等,
和驼峰的区别是,驼峰首字母小写)

而c++(标准库)则喜欢这种snake case格式
蛇形命名法:小写单词,中间用下划线连接)

#if 0
// 注释
#endif

使用using namespace std:在足够小的作用域去使用

不要在头文件使用!!!


网站公告

今日签到

点亮在社区的每一天
去签到