C++ 1114 2

xiaoxiao2021-02-28  28

关键字 =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 function bool isLucky(char) = delete; // reject chars bool isLucky(bool) = delete; // reject bools bool 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++98 typedef std::unique_ptr<std::unordered_map<std::string,std::string>> Uptrmap; //same with C++ 11 using Uptrmap = std::unique_ptr<std::unordered_map<std::string,std::string>>; typedef void (*Fn) (int, const std::string&); //same with using Fn = void (*)(int, const std::string&); //容易识别Fn为其别名 //以下为区别 typedef cannot be a template template <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 func std::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 _ForwardIterator max(_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(); } 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_if bool 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

模版内模版 非类型实参参考: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

转载请注明原文地址: https://www.6miu.com/read-600325.html

最新回复(0)