c++11新特性遇见一个记一个

std::function

std::function是函数模板类(是一个类);std::bind是函数模板(是一个函数);

#include <memory>
#include <iostream>
#include <functional>

using namespace std;

void hello(){
    cout << "hello" << endl;
}

class A
{
public:
    void fun(){};
    static void fun2(){};
private:
    static void fun3(){};
};

int main ()
{
    void(*p)() = hello;
    p();
    // function 是个函数模板类, fun1 其实是一个实例化的类哦 = 是重载后的
   function<void(void)> fun = hello;
   fun();
   // 不可指向非静态成员函数
//   fun = A::fun;
   fun = A::fun2;
   // 私有静态函数受保护
//   fun = A::fun3;

}

std::move

可以理解作用是把左值改成右值
什么是左值,什么是右值,简单说左值可以赋值,右值不可以赋值。以下面代码为例,“ A a = getA();”该语句中a是左值,getA()的返回值是右值。“hello”也是右值,你不能 “hello” = “world”
1.c++11以后,stl 都支持移动构造函数,支持move。

2.自定义的类,自己要实现移动构造函数,move才有效。

3.使用了move以后,原对象不可以继续使用了

#include <iostream>
#include <iostream>
#include <string>

class A
{
public:
    A(){std::cout << "A Constructor" << std::endl;}
    A(const A&) { std::cout << "A Copy Constructor" << std::endl; }
    ~A() {std::cout << "A Destructor" << std::endl;}
    int num;
};

class B
{
public:
    B(){ std::cout << "B Constructor" << std::endl; }
    B(const B&) { std::cout << "B Copy Constructor" << std::endl; }
    B(const B&&  ) { std::cout << "B Move Constructor" << std::endl; }
    ~B() { std::cout << "B Destructor" << std::endl; }
    int num;
};


static A getA()
{
//    char max[1048576000]; //恰好为10M,出现段错误
    static int count = 0;
    A a;
    std::cout << "getA(),cout : " << count++ << " temporary a : " << &a << std::endl;
    return a;
}

B getB(A a){
    B b;
    A a1;
    std::cout<< " temporary a address: " << &a << std::endl;
    std::cout<< " temporary b address: " << &b << std::endl;
    std::cout<< " temporary a1 address: " << &a1 << std::endl;
    return b;
}

void printStep(int count){
    std::cout << "********* Step:" << count << " *********" <<std::endl;
}

int main()
{
    std::cout << "*********  sizeof (B):" <<  sizeof (B) << " *********" <<std::endl;
   A a;

   printStep(1);
   getB(a);
   printStep(2);
//   B b;
   B b = getB(a); // 你以为调移动构造,编译器给你悄悄优化了。
   getA();
   std::cout << "b address:" << &b << std::endl;


//   printStep(3);
//   B b1 = b;
//   std::cout << "b1 address:" << &b1 << std::endl;

//   printStep(4);
//   B b3 = std::move(b1);
//   std::cout << "b3 address:" << &b3 << std::endl;
//   std::cout << "b1 address:" << &b1 << std::endl;

   return 0;
}

decltype 类型推导,拖尾返回

/* **** 编译不过
template<typename R, typename T, typename U>
R add(T x, U y) {
    return x+y
}
*/
template<typename T, typename U>
auto add(T x, U y) -> decltype(x+y) {
    return x+y;
}

thread_local

local_thread 是 C++11 新增的线程局部存储(Thread Local Storage,TLS)机制,它可以让每个线程拥有自己的局部变量,这些变量对于该线程来说是唯一的,不同线程之间的变量互不干扰。在多线程编程中,线程局部存储是一种非常有用的机制,它可以避免多个线程同时访问同一个全局变量所带来的竞争和同步问题。

使用 local_thread 很简单,只需要在变量声明前加上 thread_local 关键字即可,例如:

thread_local int i;
这样就定义了一个线程局部变量 i,每个线程都有各自的 i 变量。线程局部变量的生命周期与线程一样长,当线程退出时,它的局部变量也会被销毁。

local_thread 有以下几个特点:

局部变量的初始化方式与普通变量相同,可以使用默认构造函数、拷贝构造函数、移动构造函数等方式初始化。
局部变量的存储位置是在线程的栈上,不同线程的局部变量存储位置不同。
局部变量的地址在不同线程中是不同的,不能跨线程访问。
局部变量的生命周期与线程一样长,当线程退出时,它的局部变量也会被销毁。
需要注意的是,local_thread 不能用于全局变量或静态变量,它只能用于函数内部或类的成员变量中。

local_thread 给多线程编程带来了很大的便利,它可以让每个线程拥有自己的独立变量,避免了多个线程同时访问同一个全局变量所带来的问题。同时,local_thread 也需要注意一些细节,比如不能跨线程访问、不能用于全局变量或静态变量等。在多线程编程中,合理地使用 local_thread 可以提高程序的性能和可维护性。

std::upper_bound() 和 std::lower_bound()

要求容器必须有序,他俩底层都是二分法查找
std::lower_bound() 是在区间内找到第一个大于等于 value 的值的位置并返回,如果没找到就返回 end() 位置。而 std::upper_bound() 是找到第一个大于 value 值的位置并返回,如果找不到同样返回 end() 位置。
对于容器中对象使用时。第四个参数会 使用个自定义的函数 或 lambda 表达式

std::vector<Obj> vec;
Obj temp;
// 匿名函数中 l 第一个参数 是temp。 r 是循环的迭代器
vec.insert(std::upper_bound(vec.begin(), vec,end(), temp, [](const Obj &l, const Obj &r){ return l.num < r.num }),  temp);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值