C++基础篇:01 简介

1 历史由来

        本贾尼.斯特劳斯特卢普,于1979年在贝尔实验室分析UNIX系统分布式内核的流量时,特别希望有一种更加模块化的工具,于是在1979年10月时开始着手开发一块新的编程语言,在c语言的基础上增加了面向对象的机制,这就是C++。1983年完成了C++的第一个版本

2 C++与C的重要区别

① C++是完全兼容C语言的所有内容

② C++支持面向对象的编程思想

③ C++支持运算符重载、函数重载的编译时多态机制

④ C++支持泛型编程、模板机制

⑥ C++支持异常处理

⑦ C++的类型检查更加严格

⑧ C++增加了名字空间

  注意:学习C++的重点是学习面向对象的编程思想,而不是花里胡哨的各种特殊语法

3 第一个C++程序:helo world

    #include 
    using namespace std;
    int main(int argc,const char* argv[])
    {
        cout << "hello world" << endl
        return 0;
    }

注意:

① 文件后缀名由.c改为.cpp .cc .cxx .C

② 编译器由gcc改为g++,原来的参数还是一样。但是gcc也可以编译.cpp,需要加编译参数

            gcc xxx.cpp -xC++ -lstdc++或者gcc -xc++ xxx.cpp -lstdc++

③ C++的头文件不带.h结尾,iostream意为in out stream 在C++中输入、输出被封装成流操作,C语言的头文件还可以继续使用,但是建议使用C++重新编写的C语言头文件,原C头文件名前面+c,并去掉.h,为了删除C头文件中大量定义好的宏,然后重新放入名字空间中,为了防止与C++命名冲突stdio.h -> cstdio,stdlib.h -> cstdlib

④ C++增加了名字空间的技术:为了解决命名冲突而新增的一项技术

⑤ 输入和输出不同:cout 用于输出 cin用于输入 需要配合运算符

            cout << num << num2 << num3 << endl; endl是换行

            cin >> num >> num2 >> num3;

⑥ 不需要占位符,默认会自动识别基础类型

            printf/scanf 是C语言标准库函数

            cout/cin 是C++标准库中的类对象(类似结构变量)

4 C++与C数据类型不同

4.1 结构的不同struct

        不需要typedef对类型进行重定义,因为C++中设计好结构后,定义结构变量时不再需要struct关键字

        结构中可以有成员函数,结构变量、指针通过.或者->访问成员函数,在成员函数中可以直接访问成员变量、成员函数,不再需要.或者->

        结构中默认下一定有一些隐藏的成员函数(构造、析构、拷贝构造、赋值函数)

        结构可以继承其它结构,也可以被其他结构继承

        可以给成员设置访问控制属性

            public      公开的(默认)

            protected   保护的

            private     私有的

4.2 联合的不同union

        不需要typedef对类型进行重定义,因为C++中设计好联合后,定义联合变量时不再需要union关键字

        联合中可以有成员函数,联合变量、指针通过.或者->访问成员函数,在成员函数中可以直接访问成员变量、成员函数,不再需要.或者->

        联合中默认下一定有一些隐藏的成员函数(构造、析构、拷贝构造、赋值函数)

        可以给成员设置访问控制属性

            public      公开的(默认)

            protected   保护的

            private     私有的

4.3 枚举的不同enum

        不需要typedef对类型进行重定义,因为C++中设计好枚举后,定义枚举变量时不再需要enum关键字

        是一种独立的数据类型(C语言用int来模拟枚举类型),不能与整型做隐式转换,只能用枚举常量

4.4 bool类型的不同

        C++中有真正的布尔类型,bool是C++中的关键字,不需要包含stdbool.h头文件,true和false也是C++的关键字

        true和false在C++中是1字节,并且是真正的布尔类型,而c语言中是int类型模拟的,是4字节,但是bool类型字节数都是1

        注意:无论C还是C++,bool类型只能存储0或1

4.5 字符串类型的不同

        C++中的字符串都被封装在string类中,可以与C语言的字符串进行转换  (.c_str()从string转为char*)

        string类被封装在string头文件中,该头文件被包含在了iostream头文件中,属于std名字空间

        使用string字符串可以通过运算符的方式直接操作字符串,原来C语言string.h系列函数也可以继续使用

        注意:C++中用string类没有规定必须以字符'\0'结尾,编译器在实际中可能在末尾加,也可能不加,这是由编译器决定的。因为string是一个类类型,它的字符串长度信息已经封装在了类的私有成员变量中,可以得知长度,不需要加'\0'了

4.6 void*类型的不同

        在C语言中,void*可以与任意类型的指针进行转换;在C++中,void*不可以自动隐式转换成其他类型的指针,如果需要赋值给其他类型的指针时,必须强制类型转换,为了提高指针的安全性考虑;在C++中,其他类型指针可以自动隐式转换成void*,C++之所以保留这个转换,是因为C语言标准库、操作系统接口函数采用了大量的void*作为函数参数,如果不保留该转换,C++在调用此类函数时会非常麻烦。例如free/realloc/bzero/mmap

5 C++名字空间

5.1 为什么需要名字空间?

        由于C++完全兼容C语言,标准库中自带了大量的宏、函数、结构、类,而且还支持继承语法,导致全局的标识符大量增加,命名冲突的风险也大大增加。

5.2 什么是名字空间

        C++中设计一种对命名空间进行逻辑划分单位的技术,称为名字空间,是一种解决命名冲突的机制。定义名字空间后,就形成了命名的封闭作用域

 namespace xxx{
            变量;
            函数;
            结构、联合、枚举;
            类;
        }

5.3 如何使用名字空间

① 域限定符访问 ::

        xxx::标识符;

② 全部直接访问

        using namespace xxx;

注意:可以直接访问xxx名字空间中的所有标识符,虽然方便,但是不建议都这样用

③ 同名名字空间可以合并

        a.cpp
        namespace n1{
            int a;
        }
        b.cpp
        namespace n1{
            int b;
        }
        main.cpp
        using namespace n1;//   会把a.cpp的a和b.cpp的b一起倒入到main.cpp中

        同名名字空间可以多处定义,不同位置的同名名字空间编译器会自动合并

④ 名字空间中的标识符可以声明与定义分离

        a.h
        namespace n1{
            extern int num; //  声明
        }
        a.cpp
        int n1::num;    //  定义

        注意:需要在定义时使用域限定符进行说明

⑤ 匿名名字空间

        所有的全局标识符都属于同一个名字空间,该名字空间没有名字,称为匿名名字空间,只要不加域限定符说明,那默认都属于匿名名字空间的标识符

        匿名名字空间中的标识符通过 ::标识符名 来访问

        例如:同名局部变量屏蔽了同名全局变量后,可以使用 ::变量名 指定访问全局变量

   

⑥ 名字空间可以嵌套

    namespace n1{
        int num = 10;
        namespace n2{
            int num = 20;
            namespace n3{
                int num = 30;  
            }
        }  
    }

        采用逐层分解的方式访问:

            n1::n2::n3::num;

        导入整个名字空间:

            using namespace n1::n2::n3;

        给名字空间换别名

                namespace n123 = n1::n2::n3;

6 C++堆内存管理

        C++中有专门管理堆内存的语句,而C语言中只能使用标准库提供的函数

语法格式:

 类型* p = new 类型名;

        new 分配内存,相当于C语言的malloc

    delete p;

        delete 释放内存,相当于C语言的free

    类型* p = new 类型名(val);

    new在分配内存时允许直接对内存进行初始化

    new/delete 不能与 malloc/free 混合使用

        类型* p = new 类型名;

        free(p);  // 虽然有些情况允许不报错,但不要这样做

        使用new分配内存时会自动调用类型的构造函数,而delete会自动调用类型的析构函数

        但是malloc/free不会调用,因此混用时可能会内存泄漏

数组的分配与释放

    类型* p = new 类型名[个数];

        分配连续多个同类型的堆内存,并且会调用多次构造函数

        类似:malloc(sizeof(类型)*个数)

    delete[] p;

        专门用于释放通过new[]申请的内存,它会自动调用多次析构函数

        注意:malloc/free、new/delete、new[]/delete[]不能混用

        使用new[]为结构、联合、类申请到的内存的首地址的前4个字节中存储了构造函数的调用次数,这样编译器在通过delete[]时就可以知道需要调用多少次析构函数

        但是普通类型没有构造、析构函数,所以不记录

重复释放

        delete与free一样不能重复释放,但都可以释放空指针  

内存分配失败

        malloc分配失败返回NULL,程序继续

        new分配失败会抛出一个异常,并立即结束程序

new和malloc的返回值

        malloc 返回一个void*类型的指针,需要强转

        new    返回一个具体类型的指针,不需要强转

malloc/free 与 new/delete 区别?

区别 malloc/free new/delete
身份 函数 运算符/关键字
参数 字节数(手动计算) 类型名(自动计算)
返回值 void* 带类型的指针
处理数组 手动计算总字节数 new 类型[个数]
扩容 realloc 无法直接处理
失败 返回NULL 抛异常
构造\析构 不调用 自动调用
初始化 无法初始化 允许初始化
头文件 包含头文件 直接使用
函数重载 不允许重载 允许重载
分配内存的位置 堆区 自由存储区

        注意:自由存储区只是一个抽象概念,与其他内存区不同,没有具体范围,默认调用new的时候,底层调用的是malloc所以此时绝大部分情况是分配在堆区,但是new可以当做运算符被程序员重载或者通过 new(地址) 类型名; 方式可以指定分配的内存首地址到其他区

你可能感兴趣的:(C++,c++,unix,linux,c语言)