zoukankan      html  css  js  c++  java
  • c/c++面试题(2)

    4.已知String类的原型是:

       class String

       {

                  public:

          String(const char* str = NULL);   //普通的构造函数

                           String(const String& that);  //拷贝构造函数

                           ~String(void);//析构函数

                           String& operator=(const String& that);//赋值函数

                           const char* c_str(void) const;//完成和C的字符串兼容;

                 private:

                           char*   m_str;

    };

    #include <iostream>
    #include <cstring>
    using namespace std;
    class String
    {
    public:
        /*一个简写的String(const char* str == NULL)
                    {
                        m_str(strcpy((new char[strlen(str?str:"")+1]),str?str:""));
                    }
         */
        String(const char* str = NULL)
        {
            if(str == NULL)
            {
                m_str = new char[1];
                *m_str = '';
            }
            else
            {
                int length = strlen(str);
                m_str = new char[length+1];
                strcpy(m_str,str);
            }
        }
        ~String(void)
        {
            if(m_str)
            {
                delete[] m_str;
                m_str = NULL;
            }
        }
        /*拷贝构造函数*/
    
        /*简单版本String(const String& that):m_str
          (strcpy(new char[strlen(that.str)+1],that.m_str))
         */    
        String(const String& that)
        {
            m_str = new char[strlen(that.m_str) + 1];
            strcpy(m_str,that.m_str);
        }
        /*简单版本的赋值运算符函数
          String& operator=(const String& that)
          {
                if(&that != this)
                {
                    String& tmep(that);
                    swap(m_str,tmp.m_str);
                }
                return *this;
          }
         */
        String& operator=(const String& that)
        {
            //检查自赋值
            if(this == &that)
                return *this;
            //释放原有的内存资源
            delete[] m_str;
            //分配新的内存资源,并复制内容
            m_str = new char[strlen(that.m_str + 1)];
            strcpy(m_str,that.m_str);
            //返回本对象的引用
            return *this;
        }
        //保证向C语言字符串的兼容
        const char* c_str(void) const
        {
            return m_str;
        }
    private:
        char* m_str;
    };
    int main(void)
    {
        String s1 = "Hello,World!";
        String s2 = s1;
        cout << s1.c_str()<< endl;
        cout << s2.c_str()<< endl;
        String s3("hello,C++!");
        s2 = s3;
        cout << s1.c_str() << endl;
        cout << s2.c_str() << endl;
    }

    当写一个赋值运算符函数的时候,它会考察你下面几个方面的内容;

    1)是否把返回值类型声明为该类型的引用,并在函数结束前返回实例自身的引用(即*this).只有返回一个引用,才可以

       允许连续赋值.

    2)是否把传入的参数的类型声明为常量引用.如果传入的参数不是引用而是实例对象,那么从行参到实参会调用

       一次复制构造函数.把参数声明为引用可以避免这样的无谓的消耗,能提高代码的效率.同时,我们在赋值运算符

       函数内不会改变传入的实例的状态,因此应该传入的引用参数加上const关键字.

    3)是否释放实例自身已有的内存,如果我们忘记在分配新内存之前释放自身已有的空间.程序将内存泄漏.

    4)是否判断传入的参数和当前的实例(*this)是不是同一个实例.如果是同一个,则不进行操作直接返回.

       如果事先不判断就进行赋值,那么释放实例自身的内存的时候就会导致严重的问题;当*this和传入的参数是

       同一个实例时,那么一番释放了自身的内存,传入参数的内存也同时被释放了,因此再也找不到需要赋值的

       内容了.

    5.联合以及大小端模式:分析下段代码的打印结果?已知采用的是大端模式;

    #include <stdio.h>
    union
    {
        int i;
        char x[4];
    } a;
    void main(void)
    {
        a.x[0] = 10;//0000 1010 低位低地址
        a.x[1] = 1;//0000 0001 高位高地址
        a.x[2] = 0;
        a.x[3] = 0; 
        printf("%#0x",a.i);  //0000 0000 0000 0000 0000 0001 0000 1010
    }

    分析:大端模式:低字节高地址;小端模式:低字节低地址;

    而数组的首地址是低地址的,由于是大端模式,所以a.x[0]实际上是i的高位,值为a;

    所以打印结果是0xa010000;

    如果是小端模式的话:a.x[0]实际上是i的低位,值为a;

    这个时候打印结果就是0x10a;

    6>写一个判断函数,来判断系统是大端模式还是小端模式?

    #include <stdio.h>
    int checkSystem(void)
    {
        union check
        {
            int i;
            char ch;
        }check;
        check.i = 1;
        return (check.ch == 1);
    }
    int main(void)
    {
        int flag = 0;
        flag = checkSystem();
        if(!flag)
        {
            printf("系统是大端模式!
    ");
        }
        else
            printf("系统是小端模式!
    ");
        return 0;
    }

    运用char和int的联合来判断,让i=1,如果这个时候取ch的值为1的话

    就证明是小端模式,因为联合取的时候肯定取的低位,而低8位的值肯定是1

    如果ch的值不是1就证明它是大端模式,其实这个时候它的结果是0;

    7.关于strlen和sizeof的区别?

    1.sizeof是一个运算符,而strlen是一个库函数,需要包含头文件<string.h>

    2.sizeof的参数可以数据类型或变量,而strlen的参数只能是一个以''结束

       的字符串.这里注意如果是字符串或字符数组里面有0字符的时候,它计算

       的是到第一个字符0为止的长度,并且不包括''或字符0;

    3.编译器在编译的时候就计算出了sizeof()的结果,而strlen函数必须是在运行

       的时候才计算出来.并且sizeof加算的是数据类型或数组所占用的内存的字节数,

       而strlen计算的是一个字符串到遇到0字符或''的长度.

    4.当sizeof以数组名当参数的时候,不会退化.而数组名作为strlen

       的参数的时候会退化为一个字符指针,指向的是字符串的首地址.

    看下面的打印结果?

    #include <stdio.h>
    #include <string.h>
    /*strlen在计算数组的长度的时候遇到0就会停止计算它的长度*/
    int main(void)
    {
        char arr[] = {1,2,0,3,4,0};
        printf("sizeof(arr) = %d,strlen(arr) = %d
    ",sizeof(arr),strlen(arr));
        return 0;
    }

    这里的sizeof(arr) = 7没有疑问?唯一的疑点是strlen(arr)的值结果不是6而是2;

    而如果写成 strlen("10111")的结果依然是5,从而可以得出结论是strlen只有在计算

    字符数组的时候才会把字符0当成是'',而在字符串中好像不是.

    再看一下下面的例子?这个例子也是典型的strlen(str)的例子.

    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        char buf[1000];
        int i = 0;
        for(i = 0;i < 1000;i++)
        {
            buf[i] = -1 - i;
            printf("%d ",buf[i]);
        }
        printf("
    ");
        printf("%d
    ",strlen(buf));
        return 0;
    }

    求buf的长度,这里的buf[0] = -1;

    当i = 127的时候buf[127] = -128; 而无符号的字符的取值范围是-128 到 127;

    所以 buf[127 + 128] = 0;即是当i = 255的时候,buf[255] = 0;即是字符0

    所以字符串的长度是0-254即是255;

     

      

     

      

  • 相关阅读:
    用vuex实现购物车功能
    Vue引入Jquery和Bootstrap
    emWin使用外部SRAM的方法
    (四)u-boot2013.01.01 for TQ210:《mkconfig分析》
    (三)u-boot2013.01.01 for TQ210:《mkconfig分析》
    Vmware出现报错The VMware Authorization Service is not running.之后无法上网解决
    Uva 10596
    Uva 10305
    要检测两个C文件的代码的抄袭情况
    MFC简易画图
  • 原文地址:https://www.cnblogs.com/yasanlun/p/3836574.html
Copyright © 2011-2022 走看看