zoukankan      html  css  js  c++  java
  • 《C++ Primer》学习笔记【第一部分 C++基础】

    第2章 

    整型的赋值:当我们试着把一个超出其范围的值赋给一个指定类型的对象时,结果如何?答案取决于类型是signed还是unsigned的。对于unsigned,编译器会将该值对unsigned类型的可能取值数目求模然后取所得值;对于signed类型,未定义行为,很多处理器处理方式和unsigned类似。

    字符串字面值的连接:std::cout << "multi-line" L"literal " << std::endl;结果未定义,即连接不同类型的行为标准未定义。

    const:全局作用域声明的const对象默认为文件的局部变量,非const变量默认为extern,要使const变量能够在其他文件访问,必须显示指定为extern。

    顶层const,规定某对象的值不能变;底层const,类型如果由底层常量定义,则不能忽略。

    更多关于const的资料

    引用:一般引用为左值引用,即只能绑定到对象上。const引用可以绑定到非常量的对象或一般表达式。右值引用必须绑定到右值表达式。

    double d = 1.0;

    const int &x = d;//ok

    const int &y = 4; //ok

    int &z = 4;//error

    int &&zz = 4;//右值引用,ok

    总结:

    非常量左值引用:只能绑定到非常量左值

    常量左值引用:可以绑定到所有类型的值,包括非常量左值、常量左值、非常量右值和常量右值

    非常量右值引用:只能绑定到非常量右值

    常量右值引用:只能绑定到非常量右值和常量右值

    指向指针的引用:int *p; int *&r = p;//从右往左读,r是一个引用,引用一个指针,这个指针指向int

    类型别名:typedef 

    注意,typedef char *pstring; const pstring cstr = 0;const pstring是一个指向char的常量指针。

    头文件:头文件用于声明而不是用于定义,但有三个例外:1.可以定义类 2.可以定义const对象 3.可以定义inline函数。

    (在头文件中加入或修改内联函数时,使用了该头文件的所有源文件都必须重新编译)

    auto说明符:auto定义的变量必须有初始值,由编译器通过初始值来推断类型。一条声明语句中,只能有一个基本类型。

    auto i = 0, *p = &i;//ok

    auto sz = 0, pi = 3.14;//error, 类型不同 

    第3章 

    命名空间的using声明:有一种情况下,必须总是使用完全限定的标准库名字:在头文件中。即头文件中,不该用“using namespace std; cout << endl; ”,而该用"std::cout << std::endl;"

    理由是头文件的内容会被预处理器复制到程序中,会造成包含该头文件的每个程序中都放置了同一using声明,不论该程序是否需要using声明。

    :: operator操作符 : 作用域操作符。在其左操作数的作用域内找到其右操作数的名字。用于访问某个命名空间的名字,如std::cout,同样地,可用于从某个类取名字,如string::size_type。

    指针和const限定符:

    const int a 等价于int const a。

    const int *p 等价于 int const *p, 表示一个指针,指向int类型的const对象。

    int * const p表示一个const指针

    记忆:const在*前还是*后

    多维数组和引用,指针

    int ia[3][4];

    int (&row)[4] = ia[1];//即*(ia+1)

    int (*p)[4] = ia+1;//从右往左读,p是一个指针,指向一个维度是4的数组,数组的元素类型是int型。

    *(*p+2) = 233;//ia[1][2] = 233

     用typedef简化指向多维数组的指针:

    typedef int int_array[4];

    int_array *ip = ia;

    第6章 

    常见宏用法

    1 防止一个头文件被重复包含 
    #ifndef BODYDEF_H 
    #define BODYDEF_H 
     //头文件内容 
    #endif
     
    
    2 得到指定地址上的一个字节或字
    #define MEM_B( x ) ( *( (byte *) (x) ) ) 
    #define MEM_W( x ) ( *( (word *) (x) ) )
    
    
    3 得到一个field在结构体(struct)中的偏移量
     #define OFFSETOF( type, field ) ( (size_t) &(( type *) 0)-> field )
    
    
    4 得到一个结构体中field所占用的字节数 
    #define FSIZ( type, field ) sizeof( ((type *) 0)->field )
    
    
    5 得到一个变量的地址(word宽度) 
    #define B_PTR( var ) ( (byte *) (void *) &(var) ) 
    #define W_PTR( var ) ( (word *) (void *) &(var) )
    
    
    6 将一个字母转换为大写
    #define UPCASE( c ) ( ((c) >= ''a'' && (c) <= ''z'') ? ((c) - 0x20) : (c) )
    
    
    7 判断字符是不是10进值的数字
    #define DECCHK( c ) ((c) >= ''0'' && (c) <= ''9'')
    
    
    8 判断字符是不是16进值的数字 
    #define HEXCHK( c ) ( ((c) >= ''0'' && (c) <= ''9'') ||((c) >= ''A'' && (c) <= ''F'') ||((c) >= ''a'' && (c) <= ''f'') )
    
    
    9 防止溢出的一个方法 
    #define INC_SAT( val ) (val = ((val)+1 > (val)) ? (val)+1 : (val))
    
    
    10 返回数组元素的个数 
    #define ARR_SIZE( a ) ( sizeof( (a) ) / sizeof( (a[0]) ) )
    
    
    11 使用一些宏跟踪调试
    ANSI标准说明了五个预定义的宏名。它们是: 
    _LINE_ /*(两个下划线),对应%d*/
    _FILE_ /*对应%s*/
    _DATE_ /*对应%s*/
    _TIME_ /*对应%s*/
    View Code
    //宏定义求max, 写完{}外面再套一个(),typeof是gnu标准而不是ISO的C标准, C语言-std=c11会报error
    #define max(x,y) ({typeof(x) _x = (x);typeof(y) _y = (y);(void)(&_x == &_y);_x > _y ? _x : _y; })
    // 不能用条件运算符
    #define MAX(a, b, Type) ({
        Type arr[] = {(a), (b)}; 
        int _i_ = ((unsigned long long)((a)-(b))) >> 63; 
        Type result[] = {arr[_i_], (a), (b), arr[_i_]}; 
        result[((((unsigned long long)(a)) >> 62)&2) | (((unsigned long long)(b)) >> 63)];
    })

    使用预处理器进行调试

    #ifndef NDEBUG

    ...

    #endif

    预处理器还定义了其余4种在调试时非常有用的常量

    __FILE__:文件名

    __LINE__:当前行号

    __TIME__:文件被编译的时间

    __DATE__:文件被编译的日期

    另一个常见的调试技术是使用NDEBUG预处理变量以及assert断言预处理宏,assert宏在cassert头文件中定义,只要NDEBUG未定义,assert就求解表达式,为false时终止程序。

    引用形参:应该将不需要修改的引用形参定义为const引用。普通的非const引用形参在使用时不灵活,这样的形参既不能用const对象初始化,也不能用字面值或产生右值的表达式初始化。

    通过引用传递数组:f(int (&arr)[10])    //OK, 是维度为10的int数组的引用

             f(int &arr[10])    //error

    多维数组的传递:int *arr[10]; //维度为10的int型指针数组

            int(*arr)[10];//arr是一个指针,指向维度为10的int型数组

    函数声明

    在头文件中提供函数声明,定义函数的源文件应包含该函数的声明。函数声明中的形参名会被忽略。既可以在声明中也可以在定义中指定默认形参,但一个文件中只能为一个形参指定默认实参一次。

    类的成员函数:含有额外的、隐含的形参; const成员函数使隐含的this形参改为const类型, 即不能修改this的数据成员; const对象、指向const对象的指针或引用只能调用其const成员函数。

     函数指针:bool (*pf) (const string &, const string &);//pf是一个指向函数的指针,该函数带两个const string&类型的形参和bool类型的返回值。

    用typedef简化函数指针的定义, typedef bool (*cmpFcn) (const string &, const string &);

    bool lengthCompare(const string &, const string &);

    cmpFcn pf1 = lengthCompare;

    lengthCompare("hi", "bye");

    pf1("hi", "bye");    //ok

    (*pf1)("hi", "bye");  //ok

    指向重载函数的指针:.....(此坑待填)

     第7章 类

    编译器只会自动地执行一步类型转换,使用多于一步类型转换总是错误的,我们必须显式完成某一步转换。

    explicit:修饰只含一个实参的构造函数,它将以直接初始化的形式使用,而且编译器不会在自动转换过程中使用该构造函数。

    标准库中接受一个参数的const char*的string构造函数不是explicit的,接受一个容量参数的vector构造函数是explicit的。

  • 相关阅读:
    计数排序
    桶排序
    给定两个数组,这两个数组是排序好的,让你求这两个数组合到一起之后第K大的数。
    leetcode349 python3 112ms 求两个数组的交集
    leetcode852 C++ 20ms 找最高峰 序列先增后减
    leetcode665 C++ 36ms 非递减数列 这题没啥意思
    leetcode414 C++ 4ms 第三大的数字
    C++ 堆排序 以及用堆排序解决topk问题
    leetcode628 python3 124ms 三个数字的最大乘积
    leetcode26 C++ 20ms 删除排序数列中的重复元素
  • 原文地址:https://www.cnblogs.com/dirge/p/6192643.html
Copyright © 2011-2022 走看看