标签:
1.ParamType是reference或pointer,不是universal reference
有引用则忽略引用,其余部分匹配T
template <typenmae T> void f(T& param); int x = 27; const int cx =x; oonst int& rx = x; f(x);//T is int, paramtype is int& f(cx);//T is const int, paramtype is coint int& f(rx);//T is const int, paramtype is coint int&2.paramType是universal reference
1)如果是lvalue,T被推导为引用,paramType也是引用
2)如果是rvalue,使用1的规则
template<typename T> void f(T&& param); int x = 27; const int cx = x; const int & rx = x; f(x);//x is lvalue, T is int&, paramtype is int& f(cx);//x is lvalue, T is const int&, paramtype is const int& f(rx);//x is lvalue, T is const int&, paramtype is const int& f(27);//27 is rvalue, T is int, paramType is int&&3.非引用,非指针
expr中有reference,忽略掉;有const,忽略掉;有volatile,忽略掉。
template<typename T> <pre name="code" class="cpp">void f(T param); int x = 27; const int cx = x; const int & rx = x;
//以下全部T paramtype都为 int f(x);f(cx);
auto于初始化braced initializer时初始化为std::initializer_list,而template type deduction不会
auto x = {1,2,3}; //类型是std::initializer_list<int>
tips:
auto作为函数返回或lambar参数时时template type deduction的方式。
此外,使用auto的情况,尤其是初始化对象的时候必须是类型明确的时候。
7.区分创建对象时的(),{}
e.g:
std::vector a(3,0); //创建3个0的vector std::vector b{1,2,3};//创建1,2,3的vector
8-15:使用新标准的关键字
nullpter代替0,
使用using代替typedef,
使用delete删除不必要的函数,
使用override表明函数覆盖,
使用const_iteratorter替代iterator,
使用noexcept在函数无异常时,
使用constexpr对编译器就能编译的函数
16.使函数具有线程安全性
C++11具有新的内存模型,支持多线程编程
17.理解编译器生成的函数
6种函数:default constructor,destructor,copy operations(copy constructor,copy assigment),move operations
move operation只在类缺少move operation,copy operation and destructor时生成
copy constructor只在缺少明确的copy constructor时生成,在move operation声明时删除。
copy assignment opetaor只在只在缺少明确的copy assignment opetaor时生成,在move operation声明时删除。
函数模板不能阻止特殊函数生成
独占资源使用std::unique_ptr,共享资源使用std::shared_ptr,配合std::shared_ptr使用std::weak_ptr;
使用std::make_unique,std::make_shared代替创建对象(不违反成对出现new,delete的原则),另外传给这两个函数的是作为被创建对象的参数。
小心循环引用。
auto_ptr复制的时候是浅复制,指向底部的区域是同一块。
std::move将对象转换为rvalue;std::forward转换为rvalue仅当参数绑定为右值,其他情况都为左值;std::move,std::forward都是编译器转换
universal reference指对象满足类型推导和&&时;universal reference转为rvalue只有参数为rvalue时,否则全为lvalue;
std::move配合rvalue使用,std::forward配合universal reference使用;
universal reference使用时避免重载,
e.g:
templte<typename T> void logandadd(T&& name){...}; void logandadd(int idx){...}; logandadd(22); //cals int overload short nameidx; logandadd(nameidx); //error
reference
collapsing:编译器生成a reference ti a
reference,结果变为一个单独的reference;只有两个都是rvalue reference才会得到rvalue reference,否则都是lvalue
reference
编译器生成后产生的情况:
template<typename T> void func(T&& param); Widget widget(); Widget w; func(w);//call func with lvalue; func(widget());//call func with rvalue熟悉std::forward失败场景,如braced initializers,0或NULL或null pointers,重载函数和模板函数,bitfield
避免默认捕获,针对每个捕获参数设置&或者=;
&捕获时,外部被捕获的对象值在生命期必须大于该闭包。否则,会出现闭包调用时,该对象已经析构;
使用init capture移动参数进入闭包
auto func = [pw = std::make_unique<Widget>()]{...};
配合auto&&和std::forward使用(C++14)
选择task-based比thread-based好。任务通常独立,降低了线程与线程间的关联,减少了线程同步的使用,自然更容易使用
std::launch::async关键字使用但异步必要的时候,launch的介绍
std::thread在所有路径上都unjoinable,对线程要么join,要么detach
使用std::future替代条件变量,(高级同步原语替代基本同步原语)
使用std::atomic,volatile修饰多线程共享变量(后者让编译器不优化,atomic的介绍
类添加对象进入私有容器时,对lvalue和rvalue参数的处理:
1.使用重载函数,一个使用lvalue参数,一个使用rvalue参数
2.使用universal reference
3.传值
三种方案的消耗:
1.一次复制对lvalue,一次移动对rvalue
2.如上
3.在函数体重,值参数被move进容器,因此比上面两种多一次move,无论lvalue还是rvalue
使用emplacement系列函数代替插入
1.减少了途中的操作,更高效
标签:
原文地址:http://blog.csdn.net/frankwyw/article/details/51366321