您的位置:首页 > 编程语言 > C语言/C++

C++ 11/14 2

2017-05-21 09:52 183 查看
关键字 =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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: