在vector中,emplace_back()成员函数的作用是在容器尾部插入一个对象,作用效果与push_back()一样,但是两者有略微差异,即emplace_back(args)中放入的对象的参数,而push_back(OBJ(args))中放入的是对象。即emplace_back()直接在容器中以传入的参数直接调用对象的构造函数构造新的对象,而push_back()中先调用对象的构造函数构造一个临时对象,再将临时对象拷贝到容器内存中。
template
class result_of
在编译时推导出一个可调用对象(std::function或重载operator())的返回值类型,主要用于模板编写。
Fn:调用对象
ArgTypes:参数列表
成员type:可调用对象的返回类型
std::result_of用法_帝江VII的博客-CSDN博客_std::result_of
std::function<int(int)> callback; ///std::function对象实例
template<typename Fn>
multimap<typename result_of<Fn(Person)>::type, Person> GroupBy(const vector<Person>& vt,const Fn& keySelect)
{
typedef typename result_of<Fn(Person)>::type key_type ///模板中的应用实例
c++11新特性之std::function和lambda表达式 - 知乎 (zhihu.com)
使用std::bind可将调用对象和参数一起绑定,绑定后结果用std::function保存,并延迟到任何需要的时候进行调用。 std::function是可调用对象的封装器,可以把std::function看作一个函数对象,用于表示函数这个抽象概念。若std::function不含目标,则称它为空,调用空的std::function的目标会抛出std::bad_function_call异常。 有时候右值会转为左值,左值会转为右值 函数模板 void G(A &&a)内部是无法知道形参对应的实参,到底是个普通变量,还是濒死的临时变量? 只能原封不动的完美的转发std::forward给函数模板 void G(A &&a)调用的下一层函数。 所以,std::forward转发问题针对的是模板函数。 定义一个匿名函数,可捕获一定范围的变量在函数内部使用。 func:lambda表达式名 capture: (1). 默认构造函数,创建一个空的 thread 执行对象。 get_id 获取线程 ID。 std::future 类模板,提供访问异步操作结果的机制,轻松从异步任务中返回结果。 包装一个可调用的对象,并且允许异步获取该可调用对象产生的结果,将其包装的可调用对象的执行结果传递给一个 std::future 对象 左值:能出现在等号左边,也能出现在等号右边的变量。可寻址的变量,有持久性。 左值引用:引用一个对象 作用:实际内部执行static_cast C++11提供的move方法会将拷贝的代价降低到最小,例如在vector中插入元素时,就可以使用move语义,减少对像的拷贝: static_cast< new_type >(expression): static_cast进行的是编译时的类型转换,只能用于已知的类型之间的转换,且不能转换掉const、volatile等属性。主要用于基本数据类型的转换、隐式转换的显式化和向上转型(子类指针或引用转为父类指针或引用)。例如: 主要用于安全的向下转型,由派生类转化为基类指针
两大作用:
1)将可调用对象与参数一起绑定,提供给另一个std::function调用
2)将n元调用对象转成m元可调用对象,绑定一部分参数 (m2、std::function
1).std::function可以绑定到全局函数/类静态成员函数(类静态成员函数与全局函数没有区别)。
2).绑定到类的非静态成员函数,则需要使用std::bind。3、std::forward
我们须要一种方法能依照參数原来的类型转发到还有一个函数中。这才完美,我们称之为完美转发。using namespace std;
void F(int& a) {
}
void F(int&& a) {
// do something
}
template<class A>
void G(A &&a) {
F(std::forward<A>(a));
}
int main (int argc, char *argv[]) {
int i = 2;
G(i); //输出 int& version
G(5);//输出 int && version
return 0;
}
3、lambda表达式
auto func = [capture] (params) opt -> ret { func_body; };
capture:捕获列表
params:参数表(可选)
opt:函数选项(可选)
ret:返回值(可选)
func_body:函数体auto func1 = [](int a) -> int { return a + 1; };
auto func2 = [](int a) { return a + 2; };
[this] { ///< 也是lambda表达式
for(;;)
{
}
}
[] 不捕获任何变量
[&] 引用捕获,捕获外部作用域所有变量,在函数体内使用引用
[=]值捕获,捕获外部作用域所有变量,在函数内使用副本。
[=, &a]值捕获外部作用域所有变量,按引用捕获a变量
[a]只值捕获a变量,不捕获其它变量
[this]捕获当前类中的this指针#include
三、C++11多线程
1、std::thread
1)构造
default (1)
thread() noexcept; ///noexcept不抛出异常,减少捕获异常的额外代码
initialization (2)
template
copy [deleted] (3)
thread (const thread&) = delete;
move (4)
thread (thread&& x) noexcept;
(2). 初始化构造函数,创建一个 thread对象,该 thread对象可被 joinable,新产生的线程会调用 fn 函数,该函数的参数由 args 给出。
(3). 拷贝构造函数(被禁用),意味着 thread 不可被拷贝构造。
(4). move 构造函数,move 构造函数,调用成功之后 x 不代表任何 thread 执行对象。
注意:可被 joinable 的 thread 对象必须在他们销毁之前被主线程 join 或者将其设置为 detached.#include
2)其他成员函数
joinable 检查线程是否可被 join。
join Join 线程。
detach Detach 线程
swap Swap 线程 。
native_handle返回 native handle。
hardware_concurrency [static]检测硬件并发特性。2、std::future
3、std::packed_task
C++11 并发指南四( 详解二 std::packaged_task 介绍) - Haippy - 博客园 (cnblogs.com)#include
四、左值和右值
右值:只能出现在等号右边的变量。不可寻址的常量,临时对象,短暂性。
左值可以修改。
int value = 3 ///< value为左值,3为右值
右值引用:必须绑定到右值的引用,可以通过&&获得右值引用class demo
{
public:
// 构造
demo() {cout << "demo()" << endl;}
// 析构
~demo() { cout << "~demo()" << endl;}
// 拷贝构造
demo(const demo&src) {cout << "demo(const demo&)" << endl;}
// 赋值重载
demo& operator=(const demo&src) {cout << "operator=" << endl;}
private:
int *m;
};
如果此时赋值重载中有大量的数据传递,则会使用值传递,在这里可以改写如下:
// 移动拷贝构造(带右值引用)
demo(demo &&src) {cout << "demo(const demo&)" << endl;}
// 移动赋值重载
demo& operator=(demo&&src) {cout << "operator=" << endl;}
/// 将临时量资源的控制权转交给当前对象,临时对象便不再持有资源
/// 没有发生任何内存开辟和数据拷贝
1、标准库std::move函数
int r1= 1;
int &&r2 = std::move(r1); ///< 省去了数据的拷贝操作
int r3 = r1;
string str = "Hello";//这里假设我们只需要将str的内容放到vector中,完成以后永远都不需要再用到str
vector<string> v;
//调用常规的拷贝构造函数,新建字符数组,拷贝数据
v.push_back(str);
//先把str转为右值引用,然后调用移动拷贝构造函数转交所有权
v.push_back(move(str));
2、类型转换
dynamic_cast< new_type >(expression):
备注:new_type为目标数据类型,expression为原始数据类型变量或者表达式。1)static_cast:静态类型转换
int a = 10; double b = static_cast(a); // 将整数a转换成浮点数b Base* ptrB = static_cast2)dynamic_cast:动态类型转换
dynamic_cast进行的是运行时的类型转换,可以在基类和派生类之间进行类型转换,并且能够检查类型是否符合转换。如果转换失败,则返回空指针或抛出std::bad_cast异常。主要用于向下转型(父类指针或引用转为子类指针或引用),但只有当父类指针或引用真正指向子类对象时才能成功转换。例如:
Derived d; Base* ptrB = &d; Derived* ptrD = dynamic_cast
综上所述,static_cast用于已知类型的静态转换,而dynamic_cast用于未知类型的动态转换。使用时需要注意类型安全和转换结果的判断。