施磊老师高级c++(七)

可变参语法

1. 基本的可变参数模板

template <typename... Args>
void func(Args... args) {
    // args 是一个参数包
}
  • typename... Args 代表 类型参数包,可以接受多个类型。
  • Args... args 代表 函数参数包,对应多个参数。

2. 可变参数展开(递归)–这个有点意思

#include <iostream>

// 终止递归的函数
void print() {
    std::cout << "End\n";
}

// 递归展开参数包
template <typename First, typename... Rest>
void print(First first, Rest... rest) {
    std::cout << first << " ";
    print(rest...);  // 递归调用
}

int main() {
    print(1, 2.5, "hello", 'A');  // 输出: 1 2.5 hello A End
}
  • 终止递归print() 解决参数包为空的情况。
  • print(first, rest...) 依次展开参数包,类似递归。

3. sizeof... 获取参数个数

template <typename... Args>
void countArgs(Args... args) {
    std::cout << "参数个数: " << sizeof...(args) << "\n";
}

int main() {
    countArgs(1, 2, 3.14, "text");  // 输出: 参数个数: 4
}

4. 结合 std::forward 进行完美转发

#include <iostream>
#include <utility>  // std::forward

void show(int& x) { std::cout << "Lvalue: " << x << "\n"; }
void show(int&& x) { std::cout << "Rvalue: " << x << "\n"; }

template <typename... Args>
void forwardArgs(Args&&... args) {
    show(std::forward<Args>(args)...);
}

int main() {
    int a = 10;
    forwardArgs(a);   // Lvalue: 10
    forwardArgs(20);  // Rvalue: 20
}
  • Args&&... args 使 args 成为 万能引用,能够接受左值和右值。
  • std::forward<Args>(args)... 保持原本的左值/右值特性,防止不必要的拷贝或移动。

5. 结合 std::initializer_list(参数展开的一种方式)

#include <iostream>

template <typename... Args>
void printAll(Args... args) {
    (std::cout << ... << args) << "\n";  // C++17 折叠表达式
}

int main() {
    printAll(1, " hello ", 3.14);  // 输出: 1 hello 3.14
}
  • (std::cout << ... << args)C++17 折叠表达式,简化递归调用。
  • 等价于((std::cout << args), ...),即 std::cout << arg1 << arg2 << arg3;

C++11容器emplace方法原理剖析(push/insert)


本文讲解C++11中的emplace

基本概念—实际就是得益于完美转发!!

在 C++ STL(标准模板库)中,emplace 是用于在容器中原地构造元素的方法,相比 insertpush_back 等方法,它可以减少不必要的对象拷贝或移动,提高性能。

核心区别

push/insert 与 emplace 直接传入对象(包括临时对象), 是没有区别的

传入 对象构造需要的 参数 , 就有区别了

emplace 不会 拷贝, push/insert 则需要拷贝

emplace传入Test对象构造所需要的参数,会直接在容器底层构造,不会产生构造和析构临时对象的额外花销,效率大大提高。

代码示例-1 – vector

#include <iostream>
#include <memory>
#include <unordered_map>
#include <list>
using namespace std;

class Test
{
public:
	Test(int) { cout << "Test(int)" << endl; }
	Test(int, int) { cout << "Test(int, int)" << endl; }
	~Test() { cout << "~Test()" << endl; }
	Test(const Test&) { cout << "Test(const Test&)" << endl; }
	Test(Test&&) { cout << "Test(Test&&)" << endl; }
};

int main()
{
	Test t1(10);
	vector<Test> vec;
	vec.reserve(10);

	// Test(int)
	// 直接插入对象,两个是没有区别的
	cout << "=================" << endl;
	// 匹配的是带左值引用参数的拷贝构造函数
	vec.push_back(t1);
	vec.emplace_back(t1);
	//Test(const Test&)
	//Test(const Test&)

	cout << "=================" << endl;
	// 匹配的是带右值引用参数的拷贝构造函数
	vec.push_back(Test(20));
	vec.emplace_back(Test(20));

	/*	Test(int)
		Test(Test&&)
		~Test()
		Test(int)
		Test(Test&&)
		~Test()*/
	cout << "=================" << endl;
	

	// 区别在这
	vec.push_back(20); /*Test(int)
						Test(Test&&)
						~Test()
*/
	vec.emplace_back(20);  // Test(int)

	//vec.push_back(30, 40); // pushback不支持多参这样传入
	vec.push_back(Test(30,40));
	vec.emplace_back(30, 40);
	cout << "=================" << endl;

	return 0;
}

代码示例-2 – map键值对 – 这个很方便

#include <iostream>
#include <string>
#include <map>
using namespace std;



int main()
{
	map<int, string> m;
	m.insert(make_pair(1, "hzh1" ));
	m.insert({ 2, "hzh2" });
	cout << "=================" << endl;
	m.emplace(3, "hzh3");  // 这个效率很高的

	return 0;
}

底层原理:

注意一下 传参时和使用时 的 可变参写法

push_back 仅使用右值引用, 使得更简便, 完美转发 很重要

#include <iostream>
#include <string>
#include <map>
using namespace std;



class Test
{
public:
	Test(int) { cout << "Test(int)" << endl; }
	Test(int, int) { cout << "Test(int, int)" << endl; }
	~Test() { cout << "~Test()" << endl; }
	Test(const Test&) { cout << "Test(const Test&)" << endl; }
	Test(Test&&) { cout << "Test(Test&&)" << endl; }
};

// 空间配置器
template<typename T>
class MyAllocator
{
public:
	// 内存开辟、释放
	T* allocate(size_t size) { return (T*)malloc(sizeof(T) * size); }
	void deallocate(void* p) { free(p); }

	// 对象构造、析构  引用折叠
	template<typename... Ty>
	void construct(T* p, Ty&&... args)
	{
		// 本例中是Test对象,args会完美转发,选择调用Test对象中不同的构造方式
		new (p) T(std::forward<Ty>(args)...);
	}
	void destroy(T* p) { p->~T(); }
};

template<typename T, typename Alloc = MyAllocator<T>>
class vector
{
public:
	vector() :_vec(nullptr), _size(0), _idx(0) {}
	// 预留内存空间
	void reserve(size_t size)
	{
		_vec = _allocator.allocate(size);
		_size = size;
	}
	// push_back  右值引用版本, 引用折叠
	template<typename Ty>
	void push_back(Ty&& val)
	{
		_allocator.construct(_vec + _idx, std::forward<Ty>(val));
		++_idx;
	}
	// emplace_back   引用折叠、模板参数包
	template<typename... Ty>
	void emplace_back(Ty&&... args)
	{
		_allocator.construct(_vec + _idx, std::forward<Ty>(args)...);
		++_idx;
	}

private:
	T* _vec;
	int _size;
	int _idx;
	Alloc _allocator;
};

int main()
{
	Test t1(10);
	vector<Test> vec;
	vec.reserve(10);


	// 直接插入对象,两个是没有区别的
	cout << "=================" << endl;
	// 匹配的是带左值引用参数的拷贝构造函数
	vec.push_back(t1);
	vec.emplace_back(t1);


	cout << "=================" << endl;
	// 匹配的是带右值引用参数的拷贝构造函数
	vec.push_back(Test(20));
	vec.emplace_back(Test(20));

	cout << "=================" << endl;


	// 区别在这
	vec.push_back(20); 
	vec.emplace_back(20); 


	//vec.push_back(Test(30, 40));
	vec.emplace_back(30, 40);
	cout << "=================" << endl;

	return 0;
}
### 施磊 C++ muduo 项目介绍 muduo是一个高性能的C++网络库,由陈硕开发并维护。此库广泛应用于高并发服务器程序的设计与实现中[^2]。 #### 主要特性 - **线程安全**:通过`shared_ptr`和`weak_ptr`解决多线程环境下共享资源的安全访问问题。 - **高效性能**:针对Linux平台进行了大量优化,能够处理大量的并发连接请求。 - **易于扩展**:提供了丰富的接口供开发者自定义协议解析逻辑和服务端业务流程控制。 #### 使用场景 适用于构建各种类型的分布式系统,特别是需要频繁通信的服务间交互模块。例如即时通讯软件、在线游戏后台等都需要依赖类似的框架来保证系统的稳定性和响应速度。 ```cpp // 创建TCP服务器实例 TcpServer server(loop, InetAddress(listenPort), "EchoServer"); server.setConnectionCallback( std::bind(&onConnection, _1)); server.setMessageCallback( std::bind(&onMessage, _1, _2, _3)); server.start(); loop.loop(); ``` 上述代码展示了如何利用muduo创建一个简单的回声(Echo) TCP Server,在这里注册了两个回调函数分别用于新连接建立以及接收到消息后的事件触发。 #### 学习路径建议 对于想要深入了解该项目的同学来说,可以从以下几个方面入手: - 阅读官方文档及注释说明; - 参考施磊老师的《C++课程笔记》系列资料中的相关内容部分[^1]; - 实践操作启动样例工程,熟悉基本命令行指令[^3];
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值