美文网首页C/C++学习
C/C++学习心得(持续更新中...)

C/C++学习心得(持续更新中...)

作者: simplson | 来源:发表于2017-11-05 23:35 被阅读0次

    1. const的用法 (正确使用const将大大改善程序的健壮性)

    • const int *p; //指针p1i所指内容是常量,可以不初始化
    • int * const p; //指针p2i是常量,所指内容可修改
    • const int * const p; //指针p3i是常量,所指内容也是常量
    • 由于const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。

    2. static的用法

    • 定义函数内局部静态变量
    • 定义文件内全局静态变量
    • 定义文件内静态函数
    • 定义类内静态成员变量和静态成员函数
    • 全局变量、静态全局变量以及静态局部变量都会被放在程序的静态数据存储区(全局可见)中,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它们与栈变量、堆变量的区别。

    3. virtual的用法

    • 虚拟继承
    • 实现多态(确定一个函数调用来自父类还是子类)
    • 纯虚函数
    • 虚析构函数
    • 虚函数必须实现,不实现编译器会报错

    4. 动态链接库中有个全局变量,两个进程中一个进程改变这个全局变量,另一个进程中使用这个全局变量是否会改变?

    答:不会改变,因为进程之间一般不共享数据,进程间通信可以通过IPC,例如共享内存等 。

    5. 进程间通信方法中哪种效率最高(共享内存、套接字、管道)?

    答:依具体的数据传输量来定,数据量<4500字节,共享内存效率最高;5000<数据量 <11000,套接字效率最高,11000<数据量,管道的效率最高。

    6. 定义一个指针,不给它初始化赋值,为什么系统给它默认的地址为0xCCCCCCCC而不是其它的?

    答:VC的Debug下是这样的,地址0x0CCCCCCCC处于内核地址空间,一般的应用程序是无权访问的,一旦访问就会报错。这样做是为了使我们在调试的时候能尽早地发现野指针,不让本该在调试阶段发现的问题从眼皮底下溜走。

    6. pthread_cond_signal后为什么要加sleep才能实现线程同步?

    答:对于条件变量来说,如果pthread_cond_signal之后没有任何线程阻塞在pthread_cond_wait上,那么此条件变量上的信号丢失。
    解决办法:用pthread_yield()函数实现让出 线程控制权;也可以用nanosleep来代替sleep 减小休眠时间。

    7. (1) map.insert(pair<char *, char *>(str1, str2)); (2) map.insert(pair<int, char *>(i, str)); 默认排序为升序, (1)中按字符串起始地址排序,(2)中按整形值排序 另外map在insert时,如果key重复,则将会替换?

    答:不会替换,只是插入失败而已

    vector<char *> vec_name;
    
    for(int i = 0; i < 2; i++)
    {
        char name[128] = {0};
        sprintf(name, "%s%d", "name", i);
        vec_name.push_back(name);  
    }
    printf("vector[0] = %s \n", vec_name[0]);
    printf("vector[1] = %s \n", vec_name[1])
    

    out:
    vector[0] = name1
    vector[1] = name1

       map <char *, int> map_name;
       map <char *, int>::iterator iter;
    
       for (int j = 0; j < 2; j++)
       {
            char key[32] = {0};
            sprintf(key, "%s%d", "name", j);
            map_name.insert ( pair <char *, int>  ( key, j ) );
       }
    
       for (iter = map_name.begin( ); iter != map_name.end( ); iter++)
       {
            printf(" iter->first = %s \n", iter->first);
            printf(" iter->second = %d \n", iter->second);
       }
    

    out:
    iter->first = name1
    iter->second = 0

    8. 自定义map中的比较函数

    struct Cmp {
      bool operator()(const char *str1, const char *str2) {
    
            if (strcmp(str1, str2) <= 0)    return 1;  //升序,反之降序
            else return 0;
      }
    };
    
    map<char *, int, Cmp>map_name;
    

    9. 自定义vector中的比较函数

    bool cmp(char a[], char b[])
    {
            if (strcmp(a, b) <= 0) return 1;    //升序
            else return 0;
    }
    
    vector<char *> clock_time
    sort(clock_time.begin(), clock_time.end(), cmp);
    

    10. 如果元素是结构体,那么,可以直接把比较函数写在结构体内。下面的程序详细说明了如何操作:

    #include <map>
    #include <string>
    #include <iostream>
    
    using namespace std;
    
    struct Info
    {
        string name ;
        float score ;
        //重载 “<”操作符,自定义排列规则
        bool operator < (const Info &a) const
        {
            //按score由大到小排列。如果要由小到大排列,使用“>”号即可
            return a.score < score ;
        }
    };
    
    int main()
    {
        map<Info, int> m;
        Info info;
        //插入元素,按键值的由小到大放入黑白树中
        info.name = "Jack";
        info.score = 60;
        m[info] = 25 ;
        info.name = "Bomi";
        info.score = 80 ;
        m[info] = 10 ;
        info.name = "Peti";
        info.score = 66.5;
        m[info] = 30;
        map<Info,int> :: iterator it ;
        for(it = m.begin(); it != m.end(); it++)
        {
            cout << (*it).second << " : ";
            cout << ((*it).first).name << " : " << ((*it).first).score << endl;
        }
        return 0 ;
    }
    

    11. 正确使用stl map中的erase方法

    • 使用删除之前的迭代器定位下一个元素。STL建议的使用方式
        for(ITER iter=mapTest.begin();iter!=mapTest.end();)
        {
          cout<<iter->first<<":"<<iter->second<<endl;
          mapTest.erase(iter++);
        }
    • erase() 成员函数返回下一个元素的迭代器
        for(ITER iter=mapTest.begin();iter!=mapTest.end();)
        {
          cout<<iter->first<<":"<<iter->second<<endl;
          iter=mapTest.erase(iter);
        }

    12. sscanf用法

    char str1[64] = {0};
    char str2[64] = {0};
    char str3[64] = {0};
    //先将 "iios/"过滤掉,再将非'@'的一串内容送到str1中
    sscanf("iios/12DDWDFF@122","%*[^/]/%[^@]", str1);
    sscanf("iios/12DDWDFF@122","%*[^/]/%s", str2);
    sscanf("iios/12DDWDFF@122","%[^/]", str3);
    printf("%s\n", str1);
    printf("%s\n", str2);
    printf("%s\n", str3);
    

    out :
    12DDWDFF
    12DDWDFF@122
    iios

            char DesiredTime[128] = {0};
            sprintf(DesiredTime, "%s", "1901-01-09 15:23:55");
            char year[16] = {0};
            char mon[16] = {0};
            char day[16] = {0};
            char hour[16] = {0};
            char min[16] = {0};
            char sec[16] = {0};
            int iYear,iMon,iDay,iHour,iMin,iSec;
            int valu;
    
            printf("\n DesiredTime = %s \n", DesiredTime);
    
            valu = sscanf(DesiredTime, "%4s-%2s-%2s %2s:%2s:%2s", year, mon, day, hour, min, sec);
            printf("valu1 = %d \n", valu);
    
            valu = sscanf(DesiredTime, "%d-%d-%d %d:%d:%d", &iYear,&iMon,&iDay,&iHour,&iMin,&iSec);
    
            printf("\n year=%s,mon=%s,day=%s,hour=%s,min=%s,sec=%s \n", year, mon, day, hour, min, sec);
            printf("\n iYear=%d,iMon=%d,iDay=%d,iHour=%d,iMin=%d,iSec=%d \n", iYear,iMon,iDay,iHour,iMin,iSec);
    
            printf("valu2 = %d \n", valu);
    

    out:
    DesiredTime = 1901-01-09 15:23:55
    valu1 = 6
    year=1901,mon=01,day=09,hour=15,min=23,sec=55
    iYear=1901,iMon=1,iDay=9,iHour=15,iMin=23,iSec=55
    valu2 = 6

    13. C代码优化方案

    • 使用尽量小的数据类型
    • 求余运算 a=a%8改为a=a&7 通常只要是求2n方的余数,均可使用位操作的方法来代替
    • 平方运算 a=pow(a, 2.0); 改为 a=a*a;
    • 用移位实现乘除法运算 a=a4;改为a=a<<2; b=b/4;改为b=b>>2; a=a9改为a=(a<<3)+a;
    • 使用复合赋值表达式 a-=1及a+=1
    • 结构体成员的布局
    • Switch语句中根据发生频率来进行case排序
    • 函数优化(Inline函数、不定义不使用的返回值、减少函数调用参数、所有函数都应该有原型定义、尽可能使用常量(const)、把本地函数声明为静态的(static))
    • 变量(register变量、同时声明多个变量优于单独声明变量、短变量名优于长变量名,应尽量使变量名短一点、在循环开始前声明变量)

    相关文章

      网友评论

        本文标题:C/C++学习心得(持续更新中...)

        本文链接:https://www.haomeiwen.com/subject/sdfkmxtx.html