C++ primer Plus回顾


Cstring
因为<cstring>提供的一系列api如strcpy等均已‘’结束,所有C-字符串已‘’结尾。
    char a[5] = {'a','b','c','d','i'};  //not a CString
    char b[5] = {'s','r','s','x',''}; // a CString
    'S'表示一个字符,“S”表示两个字符‘S’''
    数组只能在声明时初始化,声明时未初始化则只能单个赋值,数组不能赋值给另一个数组
    
strncpy函数
    如果函数在到达字符串结尾前,目标内存已用完,它将不会添加空字符,因此应这样使用该函数
    char name[20];
    strncpy(name,"Micheal bob nade and exread modify",19);
    name[19] = '';

模板类array
    vector数据长度可变,功能强大,但效率较低,数组长度固定,数据保存在静态存储区,效率更高
    为了效率更高,同时功能强大,C++创建了模板类array
    array<tpyename,arraySize> arr,array可直接赋值,a3=a4
    
string类对象
    重载了!= 可直接与string类对象或者Cstring比较

for循环新特性
    int a[5]
    for(int x : a)基于范围的循环
    
函数
    函数通过将返回值复制到指定的CPU寄存器或者内存单元将其返回

函数原型
    函数原型让编译器能够捕获参数错误并且让编译器知道如何检索返回值(多少字节)及如何解释它们(类型)
    ANSI C中,函数原型void sayHi()表示可变参数列表,C++空参数等同于void,C++中可变参数这样表示void sayHi(...)
    当且仅当 int sum(int arr[],arrSize) 与 int sum(int* arr, arrSize)时int arr[]与int*arr的含义是相同的,
    arr[]表示法提醒用户,arr不仅指向int,还指向数组的第一个成员
    指针传递时,没有产生数组的副本,仍使用的函数外的数组,并可以修改,我们用 int sum(const int arr[],arrSize)来限制其修改

const限定
    传指针可以修改指针内容,用const int* pl做参数表示指针内容不可修改,const int * const pl 表示指针地址和内容均不可以修改
内联函数
    不需要跳到指定地方,通过使用函数代码副本替换函数调用,空间换时间,与宏定义类似
引用传递
    当我们的意图是使用而非修改参数时,应使用const修饰,这样C++将在必要时生成临时变量,这样会使函数在可处理的参数种类方面
    更加的通用
    返回值为引用时函数内不要return临时变量
函数模板
    选择时显式具体化模板优于常规模板,而非函数模板优于模板
    具体化模板函数原型如下:
    template <> void swap<int>(int&,int&);
    显式实例化:
    template void swap<int>(int &,int &);无前面的<>,编译器将使用处理显示实例化时生成的模板具体化
    实例化或这样调用,在函数中 cout << add<int>(x,m)直接使用
    当函数调用可以匹配多个原型时,编译器将选择更具体的那个,不一定是模板具体化,而是转化更少的原型

编译
    在编译时,如编写UNIX系统的cmakelist.txt,只需要将源代码加入到项目之中,而不用加入头文件,只是因为#include指令管理
    头文件,不要用#include包含源代码,这样做将导致多重声明

变量
    volatile告诉编译器不要进行优化,这个优化假定寄存器中的值在两次使用中不会发生变化
    
    在默认情况下全局变量的链接性为外部的,而const全局变量的链接性为内部的,否则将其定义在头文件中,被其他源文件包含,将违反
    变量的单一性规则,应该导致编译出错,如果处于某种原因,希望某个常量的链接性是外部的,则可以这样定义:
    extern const int peoples = 56;其他文件需要使用时使用extern来声明它,常规的外部变量则不需要再定义时使用extern关键字,其他
    文件使用时用extern声明。

定位new运算符
    char buffer[100];
    int* pl = new (buffer) int[20]; 将pl的地址定位到buffer,定位new运算符只返回传递给它的地址,并且将其转换为(void*)类型,
    一般不能delete
    要通过定位new运算符使用不同地址,可以:
    char* buffer = new char[100];
    test*p1,*p2;
    p1 = new (buffer) test;
    p2 = new (buffer+sizeof(test)) test;

类与对象
    Time operator+(Time & t) 重载运算符t1+t2等同于调用t1.operator+(t2)
    类中不能定义const修饰的常量成员,因为类实际内存还未分配,会引发冲突,我们可以定义枚举或者static静态变量代替,静态变量将
    固定存储在静态区
    explicit 将阻止隐式转换 stock s1 = 19.6; not valid
    stock s1 = (stock)19.6; 显式转换可以
    operator typename() 类型转化函数,无参数无输入
    
    最常见的重载函数 ostream & operator << (ostream & os ,const obj & ob)
    {
        os << ob.member;
        return os;
    }
    类的成员函数调用时必须有显式或者隐式的对象,而DMA友元函数不包含this指针 friend ostream & operator<<(ostream & os,obj & d),
    这样若需要输出基类的成员,将不能通过域名调用,而需要将DMA指针转化为baseobj指针再调用
虚函数
    编译器处理虚函数的原理是给每个对象添加一个隐藏成员,改成员包含一个指向函数地址数组的指针,这种数组称为虚函数表,派生类对象将
    包含一个独立的虚函数表,重写的虚函数地址将代替原理的地址
    当派生类重新定义基类的同名函数而原型不同时,基类的接口将被隐藏
成员权限修改
    class student : private std::valarray<double>
    {
        public:
            using std::valarray<double> max;
    }
has-a关系除了包含类对象实现之外,也可以通过私有继承来实现
虚基类
    虚基类使得从多个类(它们的基类相同)派生出的对象只继承一个基类对象
类型转换
    dynamic_cast 适用于上行转换,dynamic_cast<new type>(expression)
    const_cast 改变值为const 或者volatile,可以删除const标签
    static_cast 适用于下行转换,进行由float到double,double到int的类型转换
    reinterpret_cast用于危险的类型转换,适用于依赖于实现的底层编程技术
智能指针
    auto_ptr
    unique_ptr
    shared_ptr
 unique_ptr比auto_ptr更安全,将在编译时报错,auto_ptr之间的赋值将导致前者放弃对象的所有权,如再有对前者指针的使用将导致访问空指针,
 unique_ptr将禁止悬挂指针的赋值,而允许临时指针的赋值
C++11新特性:
模板别名:using
之前创建别名 typedef std::vector<std::string>::iterator it;
使用using    using it = std::vector<std::string>::iterator;
差异using还可以:
template<class T>
    using arr12 = std::array<T,12>;
    std::array<double, 12> a1等同于arr12<double> a1;
lambda表达式
[z]按值访问变量 [&]按引用访问所有变量 [=]按值访问所有变量

原文地址:https://www.cnblogs.com/doulcl/p/13755071.html