• c++重点知识点


    - const加强

    在变量前加const,说明变量是常量只读属性。假如用指针去修改const常量会用什么结果。上例子:

    //a 是一个只读的常量,按照理论应该不能被修改
        const int a = 10;//内存中为a分配地址,赋值
        printf("sssss:&a:%d", &a);
        int *p = NULL;
        int *p2 = NULL;
        //当你对a取地址的时候,有一个内存空间(&a a的内存空间)
        p = (int *)&a;//此时取常量地址,同时将a值存在符号表中
        printf("&a:%d p的值:%d", &a, p);
        *p = 11;//修改内存中值
        printf("修改之后a:%d 
    ", a);//通过常量a(修饰符号表)而不是之前内存地址了。读取符号表中的值。
        printf("*p:%d 
    ", *p);//读取内存中值,此时已经修改
        printf("*p2:%d 
    ", *p2);//再次读取内存中,发现是11.
        system("pause");
    View Code

    这里写图片描述
    在c++中const变量是只读的,当声明这个变量为常量的时候,这个变量不能修改。加入用指针获取地址,修改时,会数值分配到符号表,指针可以修改数值,但是变量a的值没有变化。
    const和define区别
    (1) 编译器处理方式不同
      define宏是在预处理阶段展开。
      const常量是编译运行阶段使用。
    (2) 类型和安全检查不同
      define宏没有类型,不做任何类型检查,仅仅是展开。
      const常量有具体的类型,在编译阶段会执行类型检查。
    (3) 存储方式不同
      define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。
      const常量会在内存中分配(可以是堆中也可以是栈中)。

    (4)const 可以节省空间,避免不必要的内存分配。 例如:

    #define PI 3.14159 //常量宏 
    const doulbe Pi=3.14159; //此时并未将Pi放入ROM中 …… 
    double i=Pi; //此时为Pi分配内存,以后不再分配! 
    double I=PI; //编译期间进行宏替换,分配内存 
    double j=Pi; //没有内存分配 
    double J=PI; //再进行宏替换,又一次分配内存! 
    View Code


    const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而 #define定义的常量在内存中有若干个拷贝。
    (5) 提高了效率。 编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。

    const 与 #define的比较
    C++ 语言可以用const来定义常量,也可以用 #define来定义常量。但是前者比后者有更多的优点:
    (1) const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应)。
    (2) 有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试。

    l 【规则5-2-1】在C++ 程序中只使用const常量而不使用宏常量,即const常量完全取代宏常量。

    - 构造函数

    • 构造函数定义

      1. 在c++中有三种构造函数,构造函数是c++中用于初始化对象初始状态的特殊函数。
      2. 构造函数在对象创建是自动调用,隐身调用。
      3. 构造函数和普通成员构造函数遵循重载规则
      4. 拷贝构造函数是对象正确初始化的重要保证。
      5. 析构函数在对象周期结束时调用。
    • 拷贝构造函数

      1. 拷贝构造函数也是构造函数,用来构造对象。
      2. 拷贝构造函数和=是两个不同概念
      3. 当我们没有编写拷贝构造函数的时候便一起你会默认提供copy构造函数,执行的是浅拷贝。(test t= t2;)
      4. 函数返回 类类型是,通过复制构造函数建立临时对象。
    class Location
    {
    public:
        Location( int xx = 0 , int yy = 0 )
        {
            X = xx ;  Y = yy ;  cout << "Constructor Object.
    " ;
        }
        Location( const Location & p )      //复制构造函数
        {
            X = p.X ;  Y = p.Y ;   cout << "Copy_constructor called." << endl ;  }
        ~Location() { cout << X << "," << Y << " Object destroyed." << endl ; }
        int  GetX () { return X ; }     int GetY () { return Y ; }
    private :   int  X , Y ;
    } ;
    
    void f ( Location  p )
    {
        cout << "Funtion:" << p.GetX() << "," << p.GetY() << endl ;
    }
    // void playobjmain()
    // {
    //  Location A ( 1, 2 ) ;
    //  f ( A ) ;
    // }
    Location g()
    {
        Location A(1, 2);//构造函数调用第二次
        return A;//1、(因为返回对象类型)编译器会自动创建一个临时对象调用构造函数,调用拷贝构造函数。
        //2、因为需要返回,生命周期结束,对象A进行释放,调用析构函数
    }
    void main101()
    {
        Location B;//构造函数调用一次
        //开始进入被调用函数
        B = g();//在赋值结束后,创建的临时对象需要销毁,调用了一次析构函数
    
    }
    
    int main()
    {
        main101();//被调用函数结束了,第三次调用析构函数,析构对象B
        system("pause");
        return 0;
    }
    View Code

    内存角度分析类

    在c++中是面向对象编程,将变量(属性)和函数(方法)集中定义在一起,用于抽象描述现实世界的类。从计算机角度,程序依然由数据和代码段构成。那么从编译器角度如何完成面向对象理论到计算机程序的转化?也就是编译器如何管理类、对象、类和对象之间的关系。看一下代码:

    #include "iostream"
    using namespace std;
    class C1
    {
    public:
        int i; //4 
        int j; //4
        int k; //4
    protected:
    private:
    }; //变量很容易判断分配在内存中。
    
    class C2
    {
    public:
        int i; //4
        int j; //4
        int k; //4  
        static int m; //4
    public:
        int getK() const { return k; } //4
        void setK(int val) { k = val; } //4
    
    protected:
    private:
    }; //从上面分析中函数会提供函数函数指针,理论上是每个函数占用四个字节。如果这样的话,加入创建100多个对象,那内存不是占用很多,这样很不合理。同事变量是怎么处理的呢?实际内存大小是12,静态成员在全局区,属性整个类,不是对象。
    
    struct S1
    {
        int i;
        int j;
        int k;
    }; //12
    
    struct S2
    {
        int i;
        int j;
        int k;
        static int m;
    }; //16
    
    int main()
    {
        printf("c1:%d 
    ", sizeof(C1));
        printf("c2:%d 
    ", sizeof(C2));
        printf("s1:%d 
    ", sizeof(S1));
        printf("s2:%d 
    ", sizeof(S2));
    
        system("pause");
    }
    View Code

    那么用内存四区概念解析c++中属性和方法

    • c++类对象中成员变量和成员函数时分开存储的。
      • 成员变量:
        • 普通成员变量:存储在对象中,与struct变量有相同的内存布局和字节对齐方式
        • 静态成员变量:存储与全局数据区。
      • 成员函数:存储于代码段中。
        很多对象公用一块代码段,代码是怎么如何区分具体对象?其实在c++中类普通成员函数都隐式包含一个指向当前对象的this指针。
        静态成员函数是属于整个类的额,所以没有隐式的this指针。

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    Word和WPS插件开发总结
    WPS报表导出插件
    基于FFmpeg的教学资源库的非MP4视频转换为MP4流程
    Node-WebKit推送信息调研
    (译)OpenID Connect的常见问题与答案(二)
    (译)欢迎来到OpenID Connect(一)
    Xxl-job的使用
    ELK+filebeat安装部署监控springboot日志
    分布式事物
    Prometheus监控Centos,Mysql,Docker
  • 原文地址:https://www.cnblogs.com/polly333/p/4705667.html
Copyright © 2020-2023  润新知