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 = ‘\0‘;
        }
        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("系统是大端模式!\n");
    }
    else
        printf("系统是小端模式!\n");
    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为止的长度,并且不包括‘\0‘或字符0;

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

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

而strlen计算的是一个字符串到遇到0字符或‘\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\n",sizeof(arr),strlen(arr));
    return 0;
}

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

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

字符数组的时候才会把字符0当成是‘\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("\n");
    printf("%d\n",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;

c/c++面试题总结(2)

时间: 2024-10-07 01:59:36

c/c++面试题总结(2)的相关文章

【转】嵌入式软件工程师经典笔试题

嵌入式软件工程师经典笔试题 > 预处理器(Preprocessor) 1. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 我在这想看到几件事情: 1). #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等) 2). 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中 有多少秒而不是计算出实际的值,是更清晰而没有代价的. 3).

10个常见的Node.js面试题

如果你希望找一份有关Node.js的工作,但又不知道从哪里入手评测自己对Node.js的掌握程度. 本文就为你罗列了10个常见的Node.js面试题,分别考察了Node.js编程相关的几个主要方面. 在进入正文之前,需要提前声明两点: 这些问题只是Node.js知识体系的一个局部,并不能完全考察被面试者的实际开发能力. 对现实世界开发中遇到的问题,需要的是随机应变与团队合作,所以你可以尝试结对编程. Node.js面试题列表 什么是错误优先的回调函数? 如何避免回调地狱? 如何用Node来监听8

.NET教程:.NET 面试题之IEnumerable

.NET教程,今天给大家介绍的是:.NET 面试题之IEnumerable ,这是在面试的时候可能会碰到的一道题目,这道题的注解分为了两个部分,这一篇是第一部分! 什么是IEnumerable? IEnumerable及IEnumerable的泛型版本IEnumerable是一个接口,它只含有一个方法GetEnumerator.Enumerable这个静态类型含有很多扩展方法,其扩展的目标是IEnumerable. 实现了这个接口的类可以使用Foreach关键字进行迭代(迭代的意思是对于一个集合

java 19 - 9 finally有关的面试题

1 /* 2 * 面试题: 3 * 1:final,finally和finalize的区别 4 * final:最终的意思,可以修饰类,成员变量,成员方法 5 * 修饰类,类不能被继承 6 * 修饰变量,变量是常量 7 * 修饰方法,方法不能被重写 8 * finally:是异常处理的一部分,用于释放资源. 9 * 一般来说,代码肯定会执行,特殊情况:在执行到finally之前jvm退出了 10 * finalize:是Object类的一个方法,用于垃圾回收 11 * 12 * 2:如果catc

java面试题大全

java面试笔试题大汇总     第一,谈谈final, finally, finalize的区别. 最常被问到. 第二,Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)? 第三,Static Nested Class 和 Inner Class的不同,说得越多越好(面试题有的很笼统). 第四,&和&&的区别. 这个问得很少. 第五,HashMap和Hashtable的区

【面试】iOS 开发面试题(二)

1. 我们说的oc是动态运行时语言是什么意思? 答案:多态. 主要是将数据类型的确定由编译时,推迟到了运行时. 这个问题其实浅涉及到两个概念,运行时和多态. 简单来说,运行时机制使我们直到运行时才去决定一个对象的类别,以及调用该类别对象指定方法. 多态:不同对象以自己的方式响应相同的消息的能力叫做多态.意思就是假设生物类(life)都用有一个相同的方法-eat; 那人类属于生物,猪也属于生物,都继承了life后,实现各自的eat,但是调用是我们只需调用各自的eat方法. 也就是不同的对象以自己的

JAVA常见面试题及解答-java开发

JAVA常见面试题及解答 Java的垃圾回收总结  浅谈Java中的内部类 1)transient和volatile是java关键字吗? 如果用transient声明一个实例变量,当对象存储时,它的值不需要维持.例如: class T { transient int a;  //不需要维持 int b;  //需要维持 } 这里,如果T类的一个对象写入一个持久的存储区域,a的内容不被保存,但b的将被保存. volatile修饰符告诉编译器被volatile修饰的变量可以被程序的其他部分改变.在多

链表面试题Java实现【重要】

本文包含以下内容: 1.单链表的创建和遍历 2.求单链表中节点的个数 3.查找单链表中的倒数第k个结点(剑指offer,题15) 4.查找单链表中的中间结点 5.合并两个有序的单链表,合并之后的链表依然有序[出现频率高](剑指offer,题17) 6.单链表的反转[出现频率最高](剑指offer,题16) 7.从尾到头打印单链表(剑指offer,题5) 8.判断单链表是否有环 9.取出有环链表中,环的长度 10.单链表中,取出环的起始点(剑指offer,题56) 11.判断两个单链表相交的第一个

Android-异步任务介绍及面试题

Android-异步任务 一 什么是AsyncTask Android为了减低异步操作的开发难度,结合Handle和线程池,提供了AsyncTask.AsyncTask就是一个封装过的后台任务类, 顾名思义就是异步任务,他具有可以在后台执行耗时操作,同时可以将 执行的进度与UI进行同步的优点 因为Handle实际上就是两个线程之间的桥梁,但是数据的传递是单向的 Handle机制如下图: 而AsyncTask机制如下: 二 如何使用AsyncTask AsyncTask定义三种泛型类型Params

Java面试题全集(中)

这部分主要是与Java Web和Web Service相关的面试题. 96.阐述Servlet和CGI的区别? 答:Servlet与CGI的区别在于Servlet处于服务器进程中,它通过多线程方式运行其service()方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于Servlet. 补充:Sun Microsystems公司在1996年发布Servlet技术就是为了和CGI进行竞争,Servlet是一个特殊的Java程