c++11的新特性

c++ 新特性

auto关键字

auto 能做什么

//编译器能通过上下文,推断出auto变量的类型

auto fun(int a,int b)
{
	return a + b;
}

int main()
{
	auto a = 10;
	auto c = 'c';
	auto str = "qwe";
	return 0;
}

在c++ 14中auto 可以作为函数的返回值;
auto可以用于定义函数,不能用于声明函数,例如:

class Test
{
public:
	//会发生变异时的错误
    auto TestWork(int a ,int b);
};

nullptr用法

class Test
{
public:
	Test(int index)
	{
		cout << "Test(int)" << endl;
	}

	Test(void *ptr)
	{
		cout << "Test(void *ptr)" << endl;
	}
};

int main()
{
	Test(NULL);		//NULL 是宏定义,代表整形值0
	Test(nullptr);
}

在这里插入图片描述

for循环

int main()
{
	vector<int> vec;
	for(int i = 0; i < 10; i++)
	{
		vec.push_back(rand());
	}

	//内部迭代器实现
	for(auto val:vec)
	{
		cout << val << " ";
	}
	cout << endl;
	return 0;
}

STL

数组array

int main()
{
	//用法与普通的数组基本一样,
	//在底层封装了迭代器
	array<int,4> arr = {1,2,3,4};

	for(auto val:arr)
	{
		cout << val << " ";
	}
	cout << endl;
	int size = sizeof(arr);
	cout << "数组的字节数" << size << endl;
}

forward_list

与list 一样都是链式结构,list 采用的是双向链表,forward_list 采用的是单向链表

int main()
{
	//用法与list 的用法一样
	forward_list<int> ls;
	for(int i = 0; i < 10; i++)
	{
		ls.push_front(rand());
	}
	for(auto val:ls)
	{
		cout << val << " ";
	}
	cout <<endl;
	return 0;
}

unordered_map 与 unordered_set

使用方法与map 类似,只是底层实现的数据结构不一样,map set 基于红黑树
unordered_map 与unordered_set底层实现的数据结构是哈希表,所以在选择容器的时候,如果对数据的有序性有要求,则选择map 或则 set ;如果对有序性没有要求,则选择unordered_map 或者 ubordered_set,因为哈希表的增删查的时间复杂度都接近于O(1

int main()
{
	srand(time(0));
	unordered_map<int ,int> ma;
	for(int i = 0; i < 100; i++)
	{
		ma[rand() % 10 + 1]++;
	}

	for(auto val:ma)
	{
		cout << val.first << "==>" << val.second << endl;
	}
	return 0;
}

多线程

thread

void threadfun1()
{
	cout << "threadfun1()" << endl;
	this_thread::sleep_for(chrono::seconds(1));
	cout << "threadfun1() over" << endl;
}

void threadfun2(int a,string str)
{
	cout << a << " == >" << str << endl;
	cout << "threadfun2()" << endl;
	this_thread::sleep_for(chrono::seconds(5));
	cout << "threadfun2() over" << endl;
}
int main()
{
	//线程执行threadfun1函数
	thread t1(threadfun1);
	//线程执行threadfun2函数
	thread t2(threadfun2,10,"abc");

	//主线程等待线程的结束
	t1.join();
	cout << "t1.join()" << endl;
	//不等待现成的结束。
	t2.detach();
	cout << "t2.detach()" << endl;
	return 0;
}

atomic

atomic 为c++11 封装了原子数据类型。
从功能上看,简单地说,原子数据类型不会发生数据竞争,能直接用在多线程中而不必我们用户对其进行添加互斥资源锁的类型。从实现上,大家可以理解为这些原子类型内部自己加了锁。

atomic_int iCount;

void threadfun()
{
	for(int i = 0; i < 10000; i++)
	{
		iCount++;
	}
}

int main()
{
	vector<thread> vec;
	for(int i = 0; i < 10; i++)
	{
		vec.push_back(thread(threadfun));
	}

	for(auto &val:vec)
	{
		val.join();
	}
}

在这里插入图片描述

condition_variable

C++11中的std::condition_variable就像Linux下使用pthread_cond_wait和pthread_cond_signal一样,可以让线程休眠,直到被唤醒,再从新执行。线程等待在多线程编程中使用非常频繁,经常需要等待一些异步执行的条件的返回结果。

mutex mu;
condition_variable cv;
bool ready = false;


void threadfun(int id)
{
	cout << id << "已经到达" << endl;
	while(!ready)
	{
		unique_lock<mutex> lck(mu);
		//阻塞线程直到ready为true为止
		cv.wait(lck);
	}
}

void go()
{
	unique_lock<mutex> lck(mu);
	ready = true;
	//唤醒所以线程
	cv.notify_all();
}

int main()
{
	vector<thread> vec;
	for(int i = 0; i < 10; ++i)
	{
		vec.push_back(thread(threadfun,i));
	}

	cout << "all threads ready" << endl;
	go();
	for(auto &val:vec)
	{
		val.join();
	}
	return 0;
}

智能指针

shared_ptr

带引用计数的的智能指针,也叫强引用指针

class Test
{
public:
	Test()
	{
		cout << "Test()" << endl;
	}

	~Test()
	{
		cout << "~Test()" << endl;
	}
private:
	int *ptr;
};

int main()
{
	shared_ptr<Test> t1(new Test);
	//智能指针的拷贝构造时,不重新申请内存,不调用构造函数
	//只是将第一次开辟的内存的引用计数加一
	shared_ptr<Test> t2(t1);

	//输出2
	cout << t1.use_count() << endl;
	//输出2
	cout << t2.use_count() << endl;
	return 0;
}

weak_ptr

带引用计数的智能指针,弱引用计数

class Test
{
public:
	Test()
	{
		cout << "Test()" << endl;
	}

	~Test()
	{
		cout << "~Test()" << endl;
	}
private:
	int *ptr;
};

int main()
{
	shared_ptr<Test> t1(new Test);
	//智能指针的拷贝构造时,不重新申请内存,不调用构造函数
	//内存的引用计数不变,强引用指针的观察者数量加一
	weak_ptr<Test> t2(t1);

	//输出1
	cout << t1.use_count() << endl;
	//输出1
	cout << t2.use_count() << endl;
	return 0;
}

循环引用问题

class B;
class A
{
public:
	A()
	{
		cout << "A()" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
	shared_ptr<B> ptr_b;
};

class B
{
public:
	B()
	{
		cout << "B()" << endl;
	}
	~B()
	{
		cout << "~B()" << endl;
	}
	shared_ptr<A> ptr_a;
};

int main()
{
	shared_ptr<A> ptra(new A);
	shared_ptr<B> ptrb(new B);
	ptra->ptr_b = ptrb;
	ptrb->ptr_a = ptra;

	cout << ptra.use_count() << endl;
	cout << ptrb.use_count() << endl;
}

在这里插入图片描述
可以看到结果中调用了A B 的构造函数,但是并没有调用析构函数,说明存在内存的泄漏。产生的 原因是:

	shared_ptr<A> ptra(new A);
	shared_ptr<B> ptrb(new B);

两句分别使ptra 和 ptrb 指向了新开辟的两块内存,此时两块内存的引用计数都为1,
当执行

	ptra->ptr_b = ptrb;
	ptrb->ptr_a = ptra;

的时候,两块内存的引用计数都分别加一,两块内存的引用计数都变为2,
当程序结束的时候,ptra 指针析构,内存A的引用计数变为1,不释放内存,ptrb 指针析构,内存B 的引用计数变为1,不释放内存。所以,再程序结束的时候,两块内存的引用计数并没有变为0.
解决方法:

class B;
class A
{
public:
	A()
	{
		cout << "A()" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
	shared_ptr<B> ptr_b;
};

class B
{
public:
	B()
	{
		cout << "B()" << endl;
	}
	~B()
	{
		cout << "~B()" << endl;
	}
	weak_ptr<A> ptr_a;
};

int main()
{
	shared_ptr<A> ptra(new A);
	shared_ptr<B> ptrb(new B);
	ptra->ptr_b = ptrb;
	ptrb->ptr_a = ptra;

	cout << ptra.use_count() << endl;
	cout << ptrb.use_count() << endl;

}

在这里插入图片描述

bind

#include <iostream>
#include <functional>

using namespace std;
/*
	bind 函数的使用
*/

class comp
{
public:
	bool operator()(int a,int b)
	{
		return a > b;
	}
private:
};

bool func(int a,int b)
{
	return a > b;
}

int main()
{
	//将f指向绑定后的函数函数
	//<bool(int)>表示形参列表,返回值类型
	//绑定后的结果可以通过std::function进行保存
	//bind参数 函数指针,函数的参数列表
	function<bool(int)> f = bind(comp(), 1, std::placeholders::_1);

	//std::placeholders::_2 表示占位符,表示实参的第二个放到该位置,
	cout << bind(func, std::placeholders::_2, 1)(2,-1) << endl;

	//调用绑定后的函数
	cout << f(-1) << endl;
	return 0;
}

function

//如果一个函数的要求既能接受函数指针,也能接受函数对象
class Test
{
public:
	//function 可以结合bind 使用,对bind 的函数进行保存
	//也可以作为形参,不仅可以接受函数指针,还可以接受函数对象
	int Add(function<int(int,int)> f,int a,int b)
	{
		return f(a,b);
	}
};

int main()
{
	//类似于函数指针的用法
	void func(int);
	funtion<void(int)> f = func;
	
	return 0;
}

lambda 表达式

lambda的声明方式

[capture list] (params list) mutable exception-> return type { function body }
各项具体含义如下

1、capture list:捕获外部变量列表
2、params list:形参列表
3、mutable指示符:用来说用是否可以修改捕获的变量
4、exception:异常设定
5return type:返回类型
6、function body:函数体

此外还有几种简写的方式
在这里插入图片描述
capture list:捕获外部变量列表
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++11引入了许多特性,其中包括线程池的实现。在引用中的代码中,ZERO_ThreadPool类封装了线程池的功能。线程池的原理是通过维护一个线程队列和一个任务队列来实现的。 在初始化阶段,通过调用init函数来初始化线程池。该函数会创建指定数量的线程,并将其保存在threads_队列中。如果线程池已经被初始化过,则直接返回false。 在启动线程池后,调用start函数。该函数会循环创建指定数量的线程,并将它们放入threads_队列中。每个线程都会调用run函数来执行任务。 当调用exec函数时,会将任务添加到tasks_队列中。其中,std::bind用于绑定一个成员函数和其参数,以及占位符std::placeholders::_1表示传入的参数。 在waitForAllDone函数中,会判断atomic_是否为0且tasks_是否为空。如果是,则表示所有任务已经执行完毕,线程池可以退出。 线程池的stop函数用于停止线程池的运行。它会遍历threads_队列,并调用每个线程的join函数,等待线程执行完毕后再返回。 以上就是C++11特性线程池的基本原理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [基于C++11特性手写线程池实现](https://blog.csdn.net/m0_70418130/article/details/126805390)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值