C++ 11笔记

来源:互联网 发布:蓝叠安卓模拟器mac版 编辑:程序博客网 时间:2024/06/05 08:35
20161118添加:
http://www.cnblogs.com/haippy/p/3237213.html
https://my.oschina.net/shou1156226/blog/802859
深入应用C++ 11:代码优化与工程级应用
祁宇 著
2015.5出版
技术博客http://www.cnblogs.com/qicosmos/
本书示例代码需要支持C++ 11的编译器:
Windows:Visual Studio 2013。
Linux:GCC 4.8+或者Clang 3.4。
由于少数代码用到了boost库,还需要编译boost 1.53或更新的boost库。

chap1 使用C++ 11让程序更简洁、更现代
1.1类型推导
C++ 11引入了auto和decltype关键字实现类型推导。
1.1.1 auto类型推导
auto并不能代表一个实际的类型声明,只是一个类型声明的占位符。
使用auto声明的变量必须马上初始化,以让编译器推断出它的实际类型,并在编译时将auto占位符替换为真正的类型。
非static的局部变量默认就是具有自动存储期的。
3.auto的限制
auto是不能用于函数参数的。
4.什么时候用auto
auto简化STL迭代器(iterator)变量的定义
注意:auto是一个很强大的工具,但不加选择地随意使用auto,会带来代码可读性和可维护性的严重下降。因此,在使用auto的时候,一定要权衡好它带来的价值和相应的损失。
1.1.2 decltype关键字
若仅希望得到类型,而不需要(或不能)定义变量的时候应该怎么办呢?
C++ 11新增了decltype关键字,用来在编译时推导出一个表达式的类型。
1.1.3 返回类型后置语法——auto和decltype的综合使用

20170331添加:
5.7右值引用
右值引用的目的是为了实现“移动语义”和“完美转发”。
将普通的引用定义为Type&,那么右值引用的写法则是Type&&,通过std::move函数,可以将左值转换为右值引用,move可理解为static_cast<T&&><obj>。
C++ 11有一个定义:“基于安全的原因,具名参数将不被认定为右值,即便是右值引用,必须使用move来获取右值”。
5.7.2移动语义
移动是为了消除不必要的对象复制,为提高效率而存在的。
VS的DEBUG模式默认没有开启RVO。
在C++ 11之前,使用const A&也可以将函数内的变量取出,但由于是const引用,所以并不能对变量进行操作,而非const的右值引用则没有该限制。
3种构造方法:
默认复制构造(浅拷贝)、复制构造(深拷贝)、移动构造
5.7.3完美转发
完美转发是为了能更简洁明确地定义泛型函数——将一组参数原封不动地传给另一个函数。原封不动指的是参数数值和类型不变,参数的const属性不变。
C++ 11定义的T&&推导规则是,右值实参为右值引用,左值实参为左值引用,参数属性不变。
5.8显示虚函数重写
override和final并不是关键字,只有在特定的位置才有特殊含义,在其他地方仍可当变量来使用。为了保存向后兼容,override是选择性的。
20170409添加:
// 20170409.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
// VS2012编译
#include <set>
#include <iostream>
template <typename ObType, typename BinaryFunction>
bool isGroup12(const std::set<ObType> & S, BinaryFunction & op)
{
    /*
       isGroup returns true or false depending on whether the set S
       along with the operator op is a group in the Algebraic sense.
       That is, S is a group if and only if all the 4 following
       conditions are true:
            (1) If a, b in S, then a op b in S
            (2) If a, b, c in S, then (a + b) + c = a + (b + c)
            (3) There is an element 0 in S such that a + 0 = 0 + a for all a in S
            (4) If a in S, then there is a b in S such that a + b = b + a = 0
    */
    typename std::set<ObType>::const_iterator beg(S.cbegin()), offend(S.cend());
    bool noProblems = true;
    for (std::set<ObType>::const_iterator ia = beg; ia != offend && noProblems; ++ia)
    {
        for (std::set<ObType>::const_iterator ib = beg; ib != offend && noProblems; ++ib)
        {
            // ---------- (1) --------------
            if (S.count(op(*ia, *ib)) == 0)
                noProblems = false;
            // -----------------------------
            for (std::set<ObType>::const_iterator ic = beg; ic != offend && noProblems; ++ic)
            {
                // ---------- (2) -------------
    //is wrong
                //if (((*ia + *ib) + *ic) != (*ia + (*ib + *ic)))
                //    noProblems = false;
    if ( op( op(*ia,*ib), *ic) != op( *ia, op( *ib, *ic)))
     noProblems = false;
                // ----------------------------
            }
        }
    }
    return noProblems;
}
template <typename ObType, typename BinaryFunction>
bool isGroup3( const std::set<ObType> & S, BinaryFunction & op)
{
    // ... important define BinaryFunction as taking const args !
    typename std::set<ObType>::const_iterator beg(S.cbegin()), offend(S.cend());
    for (std::set<ObType>::const_iterator ia = beg; ia != offend; ++ia)
    {
        // ---------- (3) -------------
        /* let e be an *ia */
        ObType e = *ia;
        bool isGroup = true;
        for ( auto ia2 : S) {
            if( op(ia2, e) != ia2  || op( e, ia2) != ia2) {
                isGroup = false;
                break;
            }
            // identity found, set e_ in class to e and return
            if( isGroup) {
               // e_ = e;
               return true;
            }
        }
    }
    /* identity not found, this is not a group */
    return false;
}
template <typename T>
class Plus
{
    public:
        T operator() (const T & x, const T & y) { return x + y; }; 
};
int main()
{
#if 1
 int a1[]={0, 1, -1};
 int n1=sizeof(a1)/sizeof(int);
 std::set<int> S1(a1,a1+n1);
 int a2[]={0};
 int n2=sizeof(a2)/sizeof(int);
    std::set<int> S2(a2,a2+n2);
#else
 std::set<int> S1 = { 0, 1, -1 };//这种写法在VS2013以后支持
    std::set<int> S2 = { 0 };//这种写法在VS2013以后支持
#endif
    class Plus<int> p;
    std::cout << isGroup12(S1, p)<<std::endl;
    std::cout << isGroup3(S1, p)<<std::endl;
 system("pause");
    return 0;
}
20170413添加:
使用STL通用算法find_if()在list中搜索对象
这是find()的一个更强大的版本。这个例子演示了find_if(),它接收一个函数对象的参数作为参数,并使用它来做更复杂的评价对象是否和给出的查找条件相符。
// VS2012编译
#include <iostream>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>//greater
using namespace std;
// 类比较,重载了()操作符
class personIsIn1492
{
public:
 bool operator()(string& personRecord)
 {
  return personRecord.substr(0,4)=="1492";//第二个参数是要截的长度,不是截取结束的位置
 }
};
void Test1()
{
 list<string> persons;
 persons.push_back("1487迪亚士");
 persons.push_back("1492.10.12哥伦布 国庆日");
 persons.push_back("1519麦哲伦");
 persons.push_back("1649.1查理二世");
 persons.push_back("1774中原王伦起义");
#if 1
 /*
   捕获列表捕获的是调用该表达式函数内的局部非静态变量,对于那些函数内的静态变量和定义在函数外的变量,Lambda表达式可以直接使用。
   下面Lambda表达式中捕获了变量str,返回类型是bool。
   编译器在解释Lambda表达式时,会解释成一个未命名类的未命名对象,该类包含了一个重载函数调用操作符的函数,如果捕获列表中包含有值捕获参数时,那么该类中会有一个相对应的成员参数
 */
 string str="1492";
 list<string>::iterator personIterator = find_if (persons.begin(), persons.end(),[str](string& personRecord)->bool{
  if(personRecord.substr(0,4)==str)return true;
  return false;
 });
#else
 // 使用重载了()操作符类对象比较
 list<string>::iterator personIterator = find_if (persons.begin(), persons.end(),personIsIn1492());
#endif
 if (personIterator==persons.end()) {
  cout << "person not found in list" << endl;
 }
 else {
  cout << *personIterator << endl;
 }
}
class Grade
{
public:
    Grade(int id,string name,int score)
    {
        ID=id;
        Name=name;
        Score=score;
    }
    int ID;
    string Name;
    int Score;
};
//针对Grade的vector对象进行排序
//定义函数对象用来排序
class sort_Grade
{
//函数对象的最大好处是可以内联,效率极高
public:
 sort_Grade(){}
 bool operator()(Grade X,Grade Y)const
 {
    //return X.Score<Y.Score;//按成绩的升序排
    return X.Score>Y.Score;//按成绩的降序排
 }
};

void Test2()
{
 vector<Grade> finalGrade;
 finalGrade.push_back(Grade(1,"A",56));
 finalGrade.push_back(Grade(2,"B",57));
 finalGrade.push_back(Grade(3,"C",58));
 //当定义了用于排序的函数对象后就可以直接调用sort算法进行排序了
#if 1
 //sort中使用Lambda表达式:
 sort(finalGrade.begin(),finalGrade.end(),[](Grade X,Grade Y)->bool{
    //return X.Score<Y.Score;//按成绩的升序排
    return X.Score>Y.Score;//按成绩的降序排
 });
#else
 //排序,根据函数对象,函数对象的最大好处是可以内联,效率极高
 sort(finalGrade.begin(),finalGrade.end(),sort_Grade());
#endif
 int a=0;
}
void Test3()
{
 int a[10]={0};
 int N=5;
 vector<int> b;
 for(int i=0;i<N;i++)
 {
  cin>>a[i];
  b.push_back(a[i]);
 }
#if 1
 //sort中使用Lambda表达式:
 sort(a,a+N,[](int i,int j)->bool{
    return (i>j);//降序排
 });
 sort(b.begin(),b.end(),[](int i,int j)->bool{
    return (i<j);//升序排
 });
#else
 sort(a,a+N,greater<int>());//降序排列
 sort(b.begin(),b.end());//升序排列
#endif
 for(int i=0;i<N;i++)
  cout<<a[i]<<" ";
 cout<<endl;
 for(int i=0;i<N;i++)
  cout<<b[i]<<" ";
}
// 函数比较,例如带金牌的麻将牌排序
bool func(int i,int j,bool less,int a)
{
 //a放在最左边
 if(i==a)
  return true;
 if(j==a)
  return false;
 return less?(i<j):(i>j);//升序:降序
}
void Test4()
{
 vector<int>::iterator Iter;
 vector<int> the_vector;
 int temp;
 for( int i = 0; i < 5; i++ )
 {
  cin>>temp;
  the_vector.push_back(temp);//vector无push_front方法
 }
#if 1
 // bind函数,用于函数绑定的模版,它可以指定函数中的部分参数,也可以是全部参数
 sort(the_vector.begin(),the_vector.end(),bind(func,placeholders::_1,placeholders::_2,true,4));//升序排列,4放在最左边
 //sort(the_vector.begin(),the_vector.end(),bind(func,placeholders::_1,placeholders::_2,false,4));//降序排列,4放在最左边
#else
 sort(the_vector.begin(),the_vector.end(),less<int>());//升序排列
 //sort(the_vector.begin(),the_vector.end(),greater<int>());//降序排列
#endif
 cout<<"the_vector=";
 for(Iter=the_vector.begin();Iter!=the_vector.end();Iter++)
  cout<< " "<<*Iter;
 cout<<endl;
}
void Test5()
{
 //string str="abcdadcdefdde!@234";
 string str="ABCDADCDEFDDE!@234";
#if 0
 transform(str.begin(),str.end(),str.begin(),[](char ch)->char{return ch+1;});
#else
 // 将字符串变成大写
 //transform(str.begin(),str.end(),str.begin(),toupper);
 // 将所有的字符变成小写
    transform(str.begin(),str.end(),str.begin(),tolower);
#endif
 cout<<str;
}
int main(int argc, char* argv[])
{
   Test1();
   Test2();
   //Test3();
   Test4();
   Test5();
   system("pause");
   return 0;
}

20170417添加:
//VS2012编译
#include<cstdlib>
#include<functional>
#include<iostream>
#include<string>
using namespace std;
//ToInt成员函数的返回值与WinGDI.h的RGB宏或VB6的RGB函数值是不一致的,请不要混淆
//typedef unsigned long D3DCOLOR;
class Color
{
public:
 int mRed;
 int mGreen;
 int mBlue;
 int mAlpha;//255表示完全不透明
 static Color Black;
 static Color White;
 static Color Empty;
public:
 //缺省构造函数
 Color():mRed(0),mGreen(0),mBlue(0),mAlpha(255){}
 Color(int theRed,int theGreen,int theBlue,int theAlpha=0xFF):mRed(theRed),mGreen(theGreen),mBlue(theBlue),mAlpha(theAlpha){}
    //拷贝构造函数
 Color(const Color& c):mRed(c.mRed),mGreen(c.mGreen),mBlue(c.mBlue),mAlpha(c.mAlpha){}
 //操作符重载
 int& operator[](int theIdx);
 int operator[](int theIdx)const;
 Color& operator=(const Color& c){mRed=c.mRed;mGreen=c.mGreen;mBlue=c.mBlue;mAlpha=c.mAlpha;return *this;}
 //inline函数
 int GetRed()const{return mRed;}
 int GetGreen()const{return mGreen;}
 int GetBlue()const{return mBlue;}
 int GetAlpha()const{return mAlpha;}
 unsigned long ToInt()const{return (mAlpha<<24)|(mRed<<16)|(mGreen<<8)|(mBlue);}//返回值与D3DCOLOR_ARGB宏是一致的
   
 unsigned long ToWinRGBInt()const{return (0<<24)|(mBlue<<16)|(mGreen<<8)|(mRed);}
 static Color& WinRGBToColor(unsigned long lng);
 static unsigned char GetRedValue(unsigned long lng);
 static unsigned char GetGreenValue(unsigned long lng);
 static unsigned char GetBlueValue(unsigned long lng);
 friend ostream& operator<<(ostream& os,const Color& c);//put-to操作符<<
};
Color& Color::WinRGBToColor(unsigned long lng)
{
 unsigned char b[10]={0};
 //unsigned char b[4]={0};
 memcpy(&b[0],&lng,4);
    return Color(b[0],b[1],b[2],b[3]);
 //int i[4]={0};
 //i[0]=b[0];
 //i[1]=b[1];
 //i[2]=b[2];
 //i[3]=b[3];
 //return Color(i[0],i[1],i[2],i[3]);
 //return Color((int)b[0],(int)b[1],(int)b[2],(int)b[3]);
}

unsigned char Color::GetRedValue(unsigned long lng)
{
  return (unsigned char)(lng);
}
unsigned char Color::GetGreenValue(unsigned long lng)
{
  return (unsigned char)(unsigned short((lng)>>8));
}
unsigned char Color::GetBlueValue(unsigned long lng)
{
  return (unsigned char)((lng)>>16);
}
ostream& operator<<(ostream& os,const Color& c)
{
 os<<"ARGB:"<<c.mAlpha<<","<<c.mRed<<","<<c.mGreen<<","<<c.mBlue;
 return os;
}
int& Color::operator[](int theIdx)
{
 static int aJunk=0;
 switch(theIdx)
 {
 case 0:return mRed;
 case 1:return mGreen;
 case 2:return mBlue;
 case 3:return mAlpha;
 default:return aJunk;
 }
}
int Color::operator[](int theIdx)const
{
 switch(theIdx)
 {
 case 0:return mRed;
 case 1:return mGreen;
 case 2:return mBlue;
 case 3:return mAlpha;
 default:return 0;
 }
}
//ARGB:255,255,0,0
//4294901760
//ARGB:0,255,0,0
//16711680
//ARGB:0,0,0,255
//255
//ARGB:255,0,0,255
//4278190335
//16711680
void Test7()
{
 //const Color &theColor=Color(255,0,0);
 //const Color &theColor=Color(255,0,0,255);
    //const Color &theColor=Color(255,0,0,0);
    //const Color &theColor=Color(0,0,255,0);//blue
    const Color &theColor=Color(0,0,255,255);//blue
 cout<<theColor<<endl;
 
#if 1
 // function存放类的公有成员函数,使用bind绑定成员函数和对象指针,使用placeholders::_1~placeholders::_20占位符来表示函数的参数数量
 function<unsigned long()> mf1=bind(&Color::ToInt,theColor);
 function<unsigned long()> mf2=bind(&Color::ToWinRGBInt,theColor);
 cout<<mf1()<<endl;
 cout<<mf2()<<endl;
 // function存放静态函数
 function<Color(unsigned long)> smf1=Color::WinRGBToColor;
 Color c=smf1(16761798);
 cout<<c<<endl;
#else
 cout<</*(unsigned int)*/theColor.ToInt()<<endl;
 cout<<theColor.ToWinRGBInt()<<endl;
 //Color ret=Color::WinRGBToColor(16711680);
 Color c=Color::WinRGBToColor(16761798);
 cout<<c<<endl;
#endif
 cout<<"RGB:"<<(int)Color::GetRedValue(16761798)<<","<<(int)Color::GetGreenValue(16761798)<<","<<(int)Color::GetBlueValue(16761798)<<endl;
}
int main()
{
 Test7();
 system("pause");
 return 0;
}

//VS2012编译
//计算雅可比符号(d/n)
#include <functional>
#include <iostream>   
using namespace std;
int neg_one(int m);
int two(int m);
int Jacobi(int d,int n);
int Jacobi1(int d,int n);
function<int(int)> f1=neg_one;
function<int(int)> f2=two;
// function存放普通函数
#if 1
function<int(int,int)> JacobiSymbol=Jacobi;
#else
function<int(int,int)> JacobiSymbol=Jacobi1;//有问题
#endif
int neg_one(int m)  
{  
 if( m%4 == 1 )
  return 1;  
 if( m%4 == 3 )
  return -1;  
}  
int two(int m)  
{  
 if( m%8 == 1 || m%8 == 7 )
  return 1;  
 if( m%8 == 3 || m%8 == 5 )
  return -1; 
}
int Jacobi1(int m,int n)
{
 if(n%m==0)
  return 0;
 int q, s, t, d, mul=1;
 s=m;
 t=n; 
loon:  
     if( m>n )  
  {  
   m%=n;  
  }  
  while( m%2 == 0 )  
  {  
   m/=2; 
#if 1
   mul*=f2(n);
#else
   mul*=two(n);
#endif
  }  
  if( m == -1 )  
  {  
#if 0
   auto fun0=[=](int m)->int{  
    if( m%4 == 1 )
     return 1;  
    if( m%4 == 3 )
     return -1;  
   };
   mul*=fun0(n);
#else
   //mul*=neg_one(n);
   mul*=f1(n);
#endif
   goto mark;  
  }  
  if( m == 1 )  
  {  
   goto mark;  
  }  
  q=n;
  n=m;
  m=q;  
  if( (n-1)*(m-1)%8 != 0 )  
  {  
   mul*=-1;  
  }  
  goto loon;  
mark:  
  return mul; 
}
/*
计算雅可比符号(d/n),n>2且为奇整数
Jacobi符号的值:
 0表示d可以整除n
 1表示d是模n的平方剩余(?NOSURE)
 -1表示d是模n的非平方剩余(?NOSURE)
*/
int Jacobi(int d,int n)
{
 int x=d;
 int y=n;
 int j=1;
 int t;
 while(y>1){
  x=x%y;
  if(x>y/2){
   x=y-x;
   if(y%4==3) j=-1*j;
  }
  if(x==0) {x=1;y=0;j=0;}
  while(x%4==0){
   x=x/4; 
  }
  if(x%2==0){
   x=x/2;
   if((y%8==3)||(y%8==5)) j=-1*j;
  }
  if((x%4==3)&&(y%4==3)){
   j=-1*j;
   t=x;
   x=y;
   y=t;
  }
  else{
   t=x;
   x=y;
   y=t;
  }
 }
 return j;
}
void Test6()
{
 int n=45;
 for(int x=1;x<180;x++)
 {
     //cout<<JacobiSymbol(x,n)<< endl;
  cout<<"Jacobi(x="<<x<<"/n="<<n<<")="<<JacobiSymbol(x,n)<<endl;
 }
}
int main()  
{  
    Test6();
 system("pause");
 return 0;
}




0 0
原创粉丝点击