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);