zoukankan      html  css  js  c++  java
  • C/C++

    问:

    int a[3];          // 一维数组
    char b[3][5];      // 二维数组
    float c[3][5][7];  // 三维数组

    比较a+1,b+1,c+1;c[2][3][4]相对数组起始地址的偏移

    答:a+1代表a[1]的地址,是一级指针,要去a+1里面的内存,只需cout<<*(a+1)即可;

    b+1代表b[1]的地址,是二级指针,指向从b[1][0]开始的之后的一段内存,若要取出内容,需要用2个星号,因为是二级指针,**(b+1)代表b[1][0],*(*(b+1)+1)代表b[1][1];

    c+1代表c[1]的地址,是三级指针,指向从c[1][0][0]开始的地址,若要取出内容,需要3个星号,因为是三级指针,***c代表c[0][0][0]。我们用cout<<c,cout<<*c,cout<<**c,这三次的输出结果一样,但含义不同;

    这里需要注意的一个问题:由于b是char型的,用cout输出跟b有关的信息会有所不同。cout<<**b:输出b[0][0]这个字节,b[0][0]里面保存的是该字节的ASCII码;cout<<*b:输出的是从b[0][0]开始的字符串,到空字符null(ASCII码为0)为止;cout<<b:输出指针b本身的值,即b[0][0]的地址;

    我们测试以下语句:

    cout<<sizeof(c)<<endl;
    cout<<sizeof(*c)<<endl;
    cout<<sizeof(**c)<<endl;
    cout<<sizeof(***c)<<endl;
    得出的结果为:420     140     28    4

    c是三级指针,指向整个数组区域,3*5*7=105,105*4=420

    *c是二级指针,指向从c[0][0][0]开始到c[0][4][6]结束的一段,5*7=35,35*4=140

    **c是一级指针,指向从c[0][0][0]开始到c[0][0][6]结束的一段,7*4=28

    ***c是指针所指向内容float,sizeof(***c)相当于sizeof(float)

    c[2][3][4]地址偏移的计算:2*5*7+3*7+4=95,95*4=380,偏移量为380个字节


    问:构造函数与拷贝构造函数相关

    答:拷贝构造函数与构造函数一样,若不自定义,会调用默认的函数进行操作,默认的拷贝构造函数可以完成拷贝,默认的构造函数可以完成构造。

    一旦自定义了构造函数,就不能调用默认的函数了。比如自定义了带参数的构造函数,这时去使用无参数的构造函数时会报错。构造函数里无语句也可构造对象。

    一旦自定义了拷贝构造函数,同样不能调用默认的拷贝构造函数了。与构造函数不同的是,拷贝构造函数里什么都不写,此时完成不了拷贝。拷贝构造函数在以下4种情况调用:1.初始化Cat cat1(cat2);    2.初始化Cat cat1 = cat2;(cat2 = cat1非初始化而是赋值时,不调用拷贝函数,而是调用默认的赋值函数,若Cat类中有new语句,则需要自定义赋值函数,同默认的拷贝函数,默认的赋值函数也是位拷贝)    3.函数参数fun(cat1);     4.函数返回return cat1;

    拷贝构造函数也是构造函数,当对象初始化Cat cat1(cat2);此时不调用构造函数,而是调用拷贝构造函数完成构造和初始化的功能。


    问:静态成员变量相关

    答:在类内的只是静态变量的声明,静态变量的定义必须在类外,声明:static int x;  定义:int CLASSNAME::x = 1;  在类外使用静态变量时,可以用CLASSNAME::x或者对象名.x来调用,对象名1.x对象名2.x是一样的,因为静态变量属于整个类。


    问:全局变量和全局静态变量的区别

    答:他们都是在全局数据区,唯一一个重要的区别就是,static全局只对当前文件有效,不支持extern被外部引用,在开发中的全局变量应声明为static,防止其他文件同名变量对此变量的使用。


    问:返回引用与返回非引用相关

    答:若返回局部变量的引用,将会出问题,i和j在函数结束后生存周期到,返回它们的引用得不到想要的结果。

    int &Max(int i, int j)
    {
      return i>j ? i : j;
    }
    调用函数时,函数会为 输入的实参建立一个副本,该副本属于临时变量,返回时就返回这个副本,然后将该临时变量释放。

    #include <iostream>
    using namespace std;
    class CText
    {
    public:
        ~CText()
        {
            cout<<"析构了"<<this<<endl;
        }
    };
    CText& fRefer(CText &a)
    {
        return a;
    }
    CText fNoRefer(CText &a)
    {
        return a;
    }
    
    int main(int arge,char*argv[ ])
    {
        CText a;
        cout<<"a的地址:"<<&a<<endl;
        cout<<endl<<"------引用类型返回值------"<<endl;
        a=fRefer(a);
        cout<<endl<<"------非引用类型的返回值------"<<endl;
        a=fNoRefer(a);//此处会析构一个与a地址不一样的内存,说明析构的临时变量
        cout<<endl<<"------main结束------"<<endl;
        return 0;
    }

    参看下面的例子:由于重载运算符=函数返回的不是引用,所以将返回值++没有意义,返回的是临时变量,待该临时变量赋值给别的变量后,这个临时变量的使命就完成了,就被释放了。

    class CText
    {
    public:
        ~CText()
        {
            cout<<"析构了"<<this<<endl;
        }
        CText operator++()
        {
            x++;
            return *this;
        }
        CText operator=(CText &obj)
        {
            x = obj.x;
            return *this;
        }
    private:
        int x;
    };
    int main(int arge,char*argv[ ])
    {
        CText a(1),b(2);
        (b = a)++;
        return 0;
    }


    问:对象在内存中的布局如何

    答:这是一个比较大的问题,有许多种情况,这里给出一种最简单的情况

    1.类的数据成员之间的间隔是类中最大数据类型的整数倍

    2.数据不能跨越间隔存储

    3.成员变量的保存顺序与声明顺序有关

    class A
    {
        char a;
    public:
        short b;
        char c;
    };
    

    A中short型最大,占2个字节,所以就2字节为基本单位扩展,这里A占6个字节,我们换一下顺序就可以提高利用率:

    class A
    {
        char c;
        char a;
    public:
        short b;
    };
    这里A占4个字节

    当我们考虑继承时,情况又会如何呢?

    class A
    {
        char a;
    public:
        short b;
        char c;
    };
    
    class B:public A
    {
    public:
        int d;
    };
    A占6个字节,B占12个字节,不要以为A中的私有变量在B中就不会出现
    继承时,要按照B的要求进行对齐,B中的int占4个字节,所以要把A占的6个字节补齐为8个字节,内存图如下:




  • 相关阅读:
    常用网址
    设备像素比devicePixelRatio简单介绍
    VR虚拟红包的技术实现
    jQuery重置表单
    jQuery,遍历表格每个单元格数据。
    java 23种设计模式 链接集锦
    webstorm创建nodejs + express + jade 的web 项目
    类与类之间的几种关系
    JS 中的事件绑定、事件监听、事件委托是什么?
    简单的JavaScript图像延迟加载库Echo.js
  • 原文地址:https://www.cnblogs.com/season-peng/p/6713557.html
Copyright © 2011-2022 走看看