C++ 11/14 2

来源:互联网 发布:山东卫生厅网络直报 编辑:程序博客网 时间:2024/06/18 12:39
  • 关键字 =delete,=default,using, noexcept, override, final, decltype,
  • lambda 函数
  • variadic template parameter
  • 补充 1.make语法,2.swap, 3.exception,4.set 实现,5.remove_if meta programming. 6.虚继承,7.多继承,8.memcpy(),memset(),memcmp()9. 模版内模版

关键字 =delete,=default,using, noexcept, override, final, decltype,

1.=default 通常对于 默认构造函数,拷贝构造函数,拷贝赋值构造函数,析构函数,+ 对应的move 构造函数,如果自定义了改函数则编译器不会自动产生该构造函数。 但是为了减轻开发负担在需要默认构造函数时可以= default指定让编译器帮忙产生该类型构造函数,如果不想要该类型构造函数 可以=delete。 =default,=delete 可以在类体内部和外部
inline widget& widget::operator=(const widget&) = default;
=delete 可以用在函数提上表示禁止重载某一类函数

bool isLucky(int number);        // original functionbool isLucky(char) = delete;     // reject charsbool isLucky(bool) = delete;     // reject boolsbool isLucky(double) = delete;   // reject doubles and float

可以用来指定禁止某类模版偏特化

class Widget {public:    template<typename T>    void processPointer(T* ptr) { … }};template<> void Widget::processPointer<void>(void*) = delete; // still public, but deleted

参考:
之前的实现形式时将该方法或特化声明在private中但不实现。
想使某一类class不自动产生 拷贝构造,拷贝赋值,可以定义一个uncopyable class 将其 拷贝构造,拷贝赋值放在private中可以避免其子类实现默认或非默认拷贝构造,拷贝赋值构造函数。
http://www.cnblogs.com/xinxue/p/5503836.html
2. using

//c++98typedef std::unique_ptr<std::unordered_map<std::string,std::string>> Uptrmap;//same with C++ 11using Uptrmap = std::unique_ptr<std::unordered_map<std::string,std::string>>;typedef void (*Fn) (int, const std::string&);//same withusing Fn = void (*)(int, const std::string&);//容易识别Fn为其别名//以下为区别 typedef cannot be a templatetemplate <typename T>using Vec = std::vector<T,Myalloc<T>>Vec<int> col;//可以编译通过template<typename T>typedef std::vector<T,Myalloc<T>> Vec;//编译失败,error: a typedef cannot be a template//只能typedef std:::vector<int,Myalloc<int>> Vec;//或者template <typename T>clss Vec {    typedef std::vector<T,MyAalloc<T>> type;};Vec<int>::type col;//用在模板类内部或者进行参数传递时必须加上typename 用以指定为类型。//即typedef不能直接作为模板使用
using value_type = T;//用在类内部代替typedef T value_type;

使用 using 别名后不能特化也不能偏特化
1.typedefs don’t support templatization, but alias declarations do.
2.Alias templates avoid the “::type” suffix and, in templates, the “typename” prefix often required to refer to typedefs.
3.C++14 offers alias templates for all the C++11 type traits transformations.
参考:
https://zhuanlan.zhihu.com/p/21264013
3.noexcept
从语法上讲,noexcept修饰符有两种形式,一种就是简单地在函数声明后加上noexcept关键字。比如:
void excpt_func() noexcept;

另外一种则可以接受一个常量表达式作为参数,如下所示:
void excpt_func() noexcept (常量表达式);

常量表达式的结果会被转换成一个bool类型的值。该值为true,表示函数不会抛出异常,反之,则有可能抛出异常。这里,不带常量表达式的noexcept相当于声明了noexcept(true),即不会抛出异常。
noexcept形如其名地,表示其修饰的函数不会抛出异常。不过与throw()动态异常声明不同的是,在C++11中如果noexcept修饰的函数抛出了异常,编译器可以选择直接调用std::terminate()函数来终止程序的运行,这比基于异常机制的throw()在效率上会高一些。这是因为异常机制会带来一些额外开销,比如函数抛出异常,会导致函数栈被依次地展开(unwind),并依帧调用在本帧中已构造的自动变量的析构函数等。

#include <iostream>using namespace std;void Throw() { throw 1; }void NoBlockThrow() { Throw(); }void BlockThrow() noexcept { Throw(); }int main() {    try {        Throw();    }    catch(...) {        cout << "Found throw." << endl;     // Found throw.    }    try {        NoBlockThrow();    }    catch(...) {        cout << "Throw is not blocked." << endl;    // Throw is not blocked.    }    try {        BlockThrow();   // terminate called after throwing an instance of 'int'    }    catch(...) {        cout << "Found throw 1." << endl;    }}//

BlockThrow() 会直接 terminate不会被catch
而noexcept作为一个操作符时,通常可以用于模板。比如:

template <class T>  void fun() noexcept(noexcept(T())) {}

这里,fun函数是否是一个noexcept的函数,将由T()表达式是否会抛出异常所决定。这里的第二个noexcept就是一个noexcept操作符。当其参数是一个有可能抛出异常的表达式的时候,其返回值为false,反之为true(实际noexcept参数返回false还包括一些情况,这里就不展开讲了)。这样一来,我们就可以使模板函数根据条件实现noexcept修饰的版本或无noexcept修饰的版本。从泛型编程的角度看来,这样的设计保证了关于“函数是否抛出异常”这样的问题可以通过表达式进行推导。因此这也可以视作C++11为了更好地支持泛型编程而引入的特性。

比如在C++98中,存在着使用throw()来声明不抛出异常的函数。

template<class T> class A {  public:    static constexpr T min() throw() { return T(); }    static constexpr T max() throw() { return T(); }    static constexpr T lowest() throw() { return T(); }...而在C++11中,则使用noexcept来替换throw()。template<class T> class A {  public:    static constexpr T min() noexcept { return T(); }    static constexpr T max() noexcept  { return T(); }    static constexpr T lowest() noexcept { return T(); }...又比如,在C++98中,new可能会包含一些抛出的std::bad_alloc异常。void* operator new(std::size_t) throw(std::bad_alloc);void* operator new[](std::size_t) throw(std::bad_alloc);而在C++11中,则使用noexcept(false)来进行替代。void* operator new(std::size_t) noexcept(false);void* operator new[](std::size_t) noexcept(false);当然,noexcept更大的作用是保证应用程序的安全。比如一个类析构函数不应该抛出异常,那么对于常被析构函数调用的delete函数来说,C++11默认将delete函数设置成noexcept,就可以提高应用程序的安全性。void operator delete(void*) noexcept;void operator delete[](void*) noexcept;

特别的 you need inform C++(specially std::vector,deque)that your move constructor and destructor does not throw. Then the move constructor will be called when vector grows. if the constructor is not noexcept std::vector cannot use it. since then it cannot ensure the exception guranteesdemnaded by the standard.
参考 :
http://book.2cto.com/201306/25351.html

4.override
描述:override保留字表示当前函数重写了基类的虚函数。

目的:1.在函数比较多的情况下可以提示读者某个函数重写了基类虚函数(表示这个虚函数是从基类继承,不是派生类自己定义的);2.强制编译器检查某个函数是否重写基类虚函数,如果没有则报错。

用法:在类的成员函数参数列表后面添加该关键字既可。

例子:
class Base {
virtual void f();
};

class Derived : public Base {
void f() override; // 表示派生类重写基类虚函数f
void F() override;//错误:函数F没有重写基类任何虚函数
};

注意:override只是C++保留字,不是关键字,这意味着只有在正确的使用位置,oerride才启“关键字”的作用,其他地方可以作为标志符(如:int override;是合法的)。

相关:override还有一个姊妹保留字final。
参考:
http://www.cnblogs.com/kyxyes/p/3995937.html

5.final
用在类上表示不能被继承,用在 virtual func上表示不能被重写。
参考:
http://blog.csdn.net/nighsen/article/details/6363370

6.decltype
let compiler find the type of an expression. semantic same with pyhon type(),semantic typeof()
用法1 declare return type

template <typename T1, typename T2>auto add(T1 a, T2 b)->decltype(a+b) {}

用法2。用于meta programming

typedef typename decltype(obj)::iterator iType;

用法3.use to pass the type of lambda func

auto cmp = [](const Person& p1, const Person& p2){    return p1.name() < p2.name();}//此时想获得lambda type 用于设定set的cmp funcstd::set<Person, decltype(cmp)> coll(type);

Lambda 函数

define inline function can be used as a parameter or local obj.
format:
[]()mutalbe throwspec ->retType{}
lambda have no default constructor and no assignment operator
1. [] 不截取任何变量
2. [&} 截取外部作用域中所有变量,并作为引用在函数体中使用
3. [=] 截取外部作用域中所有变量,并拷贝一份在函数体中使用
4. [=, &foo] 截取外部作用域中所有变量,并拷贝一份在函数体中使用,但是对foo变量使用引用
5. [bar] 截取bar变量并且拷贝一份在函数体重使用,同时不截取其他变量
6. [x, &y] x按值传递,y按引用传递
7. [this] 截取当前类中的this指针。如果已经使用了&或者=就默认添加此选项。
C++ 14以后可以使用 template

template <typename T>a = [=](const T& n) {cout << T << endl;}a<int>(1)

注意lmabda在没有捕获外界变量的情况下可以直接转换为函数指针,一旦捕获了就只能转换function<…> obj;
参考:
http://blog.csdn.net/booirror/article/details/26973611
http://blog.csdn.net/u010102854/article/details/52857312
区别 function http://blog.163.com/lvan100@yeah/blog/static/6811721420127511289750/
补充 : 将析构函数定义为私有意味着只能在堆上new对象并且使用者需要自己负责destroy对象。这是由于c++语言为静态语言在编译时需要对所有静态函数检查可入性,在栈上创建的不具有可入性。
参考:http://blog.csdn.net/zyq522376829/article/details/48438037

variadic template parameter

补充 求最大值两种方式1.initializer-list

template<typename _Tp>inline _Tp max(initializer_list<_Tp> __l){    return *max_element(__l.begin(),__l.end());}template<typename _ForwardIterator>inline _ForwardIteratormax(_ForwardIterator __first,_ForwardIterator __last){    return __max_element(__first,__last,__iter_less_iter());}template<typename _ForwardIterator, typename _Compare>_ForwardIterator_max_element(_ForwardIterator __First, _ForwardIterator __Last,_Compare __comp){    if(__first == __last) return __first;    ForwardIterator __result = __first;    while(++__first != __last)        if (__comp(__result,__first))            __result = __first;    return __result;}inline _Iter_less_iter(){    return _Iter_less_iter();}
  1. variadic template parameters
int maximum(int n){    return n;}template<typename... Args>int maximum(int n, Args... args){    return std::max(n,maximum(args...));}

print tuple

template <typename... Args>ostream& operator << (ostream& os, const tuple<Args...>& t){    os << "[";    PRINT_TUPLE<0,sizeof...(Args),Args...>::print(os,t);    return os << "]"; }template<int IDX,int MAX,typename... Args>struct PRINT_TUPLE{    static void print(ostream& os, const tuple<Args...>& t ){    os << get<IDX>(t) << (IDX+1)==MAX?"":",";    PRINT_TUPLE<IDX+1,MAX,Args...>(os,t);    }};template <int MAX, typename...Args>struct PRINT_TUPLE<MAX,MAX,Args...>{    static void print (std::ostream& os,const tuple<Args...>& t){}};//end statment

- 补充 1.make语法,2.swap, 3.exception,4.set 实现,5.remove_if meta programming. 6.虚继承,7.多继承,8.memcpy(),memset(),memcmp()9. 模版内模版

##
1. make 语法
参考:
http://www.kuqin.com/shuoit/20150225/344882.html
http://lpn520.iteye.com/blog/774919
2.swap
参考:
http://www.cnblogs.com/xloogson/p/3360847.html
3.exception
参考:
http://blog.csdn.net/zkreats/article/details/50550786
http://www.cnblogs.com/crazyacking/p/4951638.html
4.set实现
set 是一个rb_tree 的adaptor具体实现如GNU4.9下

template <typename _Key, typename _Compare = s  s   td::less<_Key>,typename _Allloc = std::allocator<_Key>>class set {    typedef typename _Alloc::value_type  _Alloc_value_type;public:    typedef _Key key_type;    typedef _Key value_type;    typedef _Compare key_compare;    typedef _Compare value_compare;    typedef _Alloc allocator_type;private:    typedef typename __gnu_cxx::__alooc_traits<_Alloc>::template    rebind<_Key>::other _Key_alloc_type;    typedef _Rb_tree<key_type, value_type, Identity<value_type>,    key_compare, _Key_alloc_type> _Rep_type;    _Rep_type _M_t;//adaptor define rb_tree     typedef __gnu_cxx::__alloc_traits<_Key_alloc_type> _Alloc_traits;public:    //Iterator relaited typedef    typedef typename _Alloc_traits::pointer pointer;    typedef typename _Alloc_traits::const_pointer const_pointer;    typedef typename _Alloc_traits::reference reference;    typedef typename _Alloc_traits::const_reference const_reference;    typedef typename _Rep_type::const_iterator iterator;    typedef typename _Rep_type::const_iterator const_iterator;    typedef typename _Rep_type::const_reverse_iterator reverse_iterator;    typedef typename _Rep_type::const_reverse_ierator const_reverse_iterator;    typedef typename _Rep_type::size_type size_type;    typedef typename _Rep_type::difference_type difference_type;    set():_M_t(){}    explicit    set(const _Compare& __comp,    const allocator_type& __a = allocator_type())    :_M_t(__comp,__key_alloc_type(__a)){}    ....    //C++11    set(set&& __x)    noexcept(is_nothrow_copy_constructible<_Compare>::value)    :_M_t(std::move(__x._M_t)){}    set(initializer_list<value_type> __l,    const allocator_type& __a = allocator_type())    :_M_t(__comp,_Key_alloc_type(__a))    //所有操作均是调用rb_tree内来实现};

使用:

#include <iostream>#include <set>bool fncomp (int lhs, int rhs) {return lhs<rhs;}struct classcomp {  bool operator() (const int& lhs, const int& rhs) const  {return lhs<rhs;}};int main (){  std::set<int> first;                           // empty set of ints  int myints[]= {10,20,30,40,50};  std::set<int> second (myints,myints+5);        // range  std::set<int> third (second);                  // a copy of second  std::set<int> fourth (second.begin(), second.end());  // iterator ctor.  std::set<int,classcomp> fifth;                 // class as Compare  bool(*fn_pt)(int,int) = fncomp;  std::set<int,bool(*)(int,int)> sixth (fn_pt);  // function pointer as Compare  return 0;}

参考:http://www.cplusplus.com/reference/set/set/set/
http://blog.csdn.net/jinzhilong580231/article/details/8666877
5.remove_if meta programming
http://blog.csdn.net/tianshuai1111/article/details/7674327

partial_sum 实现Fib

array<int, 10> input;//不会默认初始化array<int,10> result;for(int i = 0; i < input.size();i++){    input[i] = i;//replace(iv.begin(),iv.end(),6,3);初始化可以用replace    result[i] = 0;}partial_sum(input.begin(),input.end(),result.begin(),plus2<int>());//accumulate()int my_sum(int a, int b){return a + b;}

模板实现编译其期间Fib

template<int N>class Fib {public:    enum{Result = Fib<N-1>::Result + Fib<N-2>::Result};};template<>Fib<1>class Fib {    enum{Result = 1};};template<>Fib<0>class Fib{    enum{Result = 0};}

累加vector使用lambda

std::for_each(vector.begin(), vector.end(), [&] (int n) {    sum_of_elems += n;});

补充python 实现fib http://blog.csdn.net/buaa_shang/article/details/8283309

remove_if 使用

// remove_if example#include <iostream>     // std::cout#include <algorithm>    // std::remove_ifbool IsOdd (int i) { return ((i%2)==1); }int main () {  int myints[] = {1,2,3,4,5,6,7,8,9};            // 1 2 3 4 5 6 7 8 9  // bounds of range:  int* pbegin = myints;                          // ^  int* pend = myints+sizeof(myints)/sizeof(int); // ^                 ^  pend = std::remove_if (pbegin, pend, IsOdd);   // 2 4 6 8 ? ? ? ? ?                                                 // ^       ^  std::cout << "the range contains:";  for (int* p=pbegin; p!=pend; ++p)    std::cout << ' ' << *p;  std::cout << '\n';  return 0;}

6.虚继承,多继承
https://www.oschina.net/translate/cpp-virtual-inheritance
http://blog.csdn.net/wangxingbao4227/article/details/6772579
http://blog.csdn.net/u013630349/article/details/47057929

7.memcpy(),memset(),memcmp()
注意区分POD(plain old data)
http://www.cnblogs.com/jingliming/p/4737409.html
http://www.cnblogs.com/mayingkun/p/3234137.html

  1. 模版内模版
    非类型实参参考:http://www.cnblogs.com/gw811/archive/2012/10/25/2738929.html
    http://www.cnblogs.com/gw811/archive/2012/10/25/2736224.html

重点参考http://www.cnblogs.com/assemble8086/archive/2011/10/02/2198308.html