C/C++求职宝典21个重点笔记(常考笔试面试点)(一)

2015-01-27 06:04:49 · 作者: · 浏览: 23
  1. char c = '\72'; 中的\72代表一个字符,72是八进制数,代表ASCII码字符“:”。

  2. 10*a++ 中a先进行乘法运算再自增(笔试中经常喜欢出这类运算符优先级容易混淆的输出问题)。

  3. const和static的作用
    太常见的问题了,下面给出一个较详细的参考答案:

    static关键字:

    1)函数体内static变量的作用范围为函数体。不同于auto变量。该变量的内存只被分配一次。因此其值在下次调用时仍维持上次的值。

    2)在模块内的static全局变量可以被模块内的所有函数访问。但不能被模块外的其他函数访问。

    3)在模块内的static函数只可被这一模块内的其它函数调用。这个函数的使用范围被限制在声明它的模块内。

    4)在类中的static成员变量属于整个类所有,对类的所有对象只有一份复制。

    5)在类中的static成员函数属于整个类所有,这个函数不接受this指针,因而只能访问类的static成员变量。

    const关键字:

    1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化。因为以后就没有机会再改变它了。

    2)对指针来说,可以指定指针的本身为const,也可以指定指针所指向的数为const。或二者同时为const。

    3)在一个函数的声明中,const可以修饰形参,表明它是一个输入参数。在函数内不能改变其值。

    4)对于类的成员函数,若指定其为const类型。则表明其是一个常量函数。不能修改类的成员变量。

    5)对于类的成员函数,有时候必须指定其返回值为const类型。以使得其返回值不为“左值”。

  4. 注意sizeof不是函数而是运算符,所以在计算变量所占用空间大小时,括号是可以省略的,但在计算类型大小时括号则不能省略,比如int i = 0; 则sizeof int是错误的。

  5. 有1,2,…,n的无序数组,求排序算法,并且要求时间复杂度为O(n),空间复杂度O(1),使用交换,而且一次只能交换两个数。

    
    #include 
         
           int main() { int a[] = {10, 6, 9, 5, 2, 8, 4, 7, 1, 3}; int i, tmp; int len = sizeof(a) / sizeof(a[0]); for(i = 0; i < len;) { tmp = a[a[i] - 1]; a[a[i] - 1] = a[i]; a[i] = tmp; if(a[i] == i + 1) i++; } for(i = 0; i < len; ++i) printf("%d ", a[i]); printf("\n"); return 0; }
         
  6. 易误解:如果int a[5], 那么a与&a是等价的,因为两者地址相同。
    解答:一定要注意a与&a是不一样的,虽然两者地址相同,但意义不一样,&a是整个数组对象的首地址,而a是数组首地址,也就是a[0]的地址,a的类型是int[5],a[0]的类型是int,因此&a+1相当于a的地址值加上sizeof(int) * 5,也就是a[5],下一个对象的地址,已经越界了,而a+1相当于a的地址加上sizeof(int),即a[1]的地址。

  7. 如何将一个小数分解成整数部分和小数部分?
    要记得利用头文件中的库函数modf,下面是函数原型(记住一些实用的库函数,避免自己重写):

    double modf(double num, double *i); // 将num分解为整数部分*i和小数部分(返回值决定)
  8. 可作为函数重载判断依据的有:参数个数、参数类型、const修饰符;
    不可以作为重载判断依据的有:返回类型。

  9. 程序输出题:

     int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
     int *p = &(a + 1)[3];
     printf("%d\n", *p);

    输出:5
    说明:因为a+1指向a的第二个元素,[3]表示再向后移动3个元素。

  10. 程序输出题:

     char str1[] = "abc";
     char str2[] = "abc";
     const char str3[] = "abc";
     const char str4[] = "abc";
     const char *str5 = "abc";
     const char *str6 = "abc";
     char *str7 = "abc";
     char *str8 = "abc";
     cout << (str1 == str2) << endl;
     cout << (str3 == str4) << endl;
     cout << (str5 == str6) << endl;
     cout << (str7 == str8) << endl;

    输出:0 0 1 1
    说明:输出str1~str8的地址为:

    0x23aa80
    0x23aa70
    0x23aa60
    0x23aa50
    0x23aa48
    0x23aa40
    0x23aa38
    0x23aa30

    输出str1~str8内容“abc”的存储地址为:

    0x23aa80
    0x23aa70
    0x23aa60
    0x23aa50
    0x100403030
    0x100403030
    0x100403030
    0x100403030

    可以发现str1~str4中的内容是存在栈上,地址各不相同,而str5~str8的内容都是存储在常量区,所以地址都相同。

    注意:

    char *str = "abc";
    printf("%p\n", str1);  
    cout << &str1 << endl;

    上面打印的是字符串 “abc”的地址,下面打印的是 str1 变量的地址。

  11. C的结构体和C++结构体的区别

    (1)C的结构体内不允许有函数存在,C++允许有内部成员函数,且允许该函数是虚函数。所以C的结构体是没有构造函数、析构函数、和this指针的。
    (2)C的结构体对内部成员变量的访问权限只能是public,而C++允许public,protected,private三种。
    (3)C语言的结构体是不可以继承的,C++的结构体是可以从其他的结构体或者类继承过来的。

    以上都是表面的区别,实际区别就是面向过程和面向对象编程思路的区别:

    C的结构体只是把数据变量给包裹起来了,并不涉及算法。
    而C++是把数据变量及对这些数据变量的相关算法给封装起来,并且给对这些数据和类不同的访问权限。
    C语言中是没有类的概念的,但是C语言可以通过结构体内创建函数指针实现面向对象思想。

  12. 如何在类中定义常量成员并为其初始化?
    解答:只能在初始化列表里对const成员初始化,像下面这样:

    class CBook {
    public:
        const double m_price;
        CBook() :m_price(8.8) { }
    };

    下面的做法是错误的:

    class CBook {
    public:
        const double m_price;
        CBook() {
            m_price = 8.8;
        }
    };

    而下面的做法虽未报错,但有个warning,也不推荐:

    class CBook {
    public:
        const double m_price = 8.8; // 注意这里若没有const则编译出错
        CBook() { }
    };
  13. 在定义类的成员函数时使用mutable关键字的作用是什么?
    解答:当需要在const方法中修改对象的数据成员时,可以在数据成员前使用mutable关键字,防止出现编译出错。例子如下:

    class CBook {
    public:
        mutable double m_price;  // 如果不加就会出错
        CBook(double price) :m_price(price) { }
        double getPrice() const; // 定义const方法
    };
    double CBook::getPrice() const {
        m_price = 9.8;
        return m_price;
    }
  14. 构造函数、拷贝构造函数、析构函数的调用点和顺序问题,如下面这个例子输出是什么?

    class CBook {
    public:
        CBook() {
            cout << "constructor is called.\n";
        }
        ~CBook() {
            cout << "destructor is called.\n";
        }
    };
    
    void invoke(CBook book) { // 对象作为函数参数,如果这里加了个&就不是了,因为加了&后是引用方式传递,形参和实参指向同一块地            
                              // 址,就不需要创建临时对象,也就不需要调用拷贝构造函数了
        cout << "invoke is called.\n";
    }
    
    int main() {
        CBook c;
        invoke(c);
    }

    解答:注意拷贝构造函数在对象作为函数参数传递时被调用,注意是对象实例而不是对象引用。因此该题输出如下:

    constructor is called.
    i