c/c++笔试、面试知识点(一)

1、extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。
(1) 被extern "C"限定的函数或变量是extern类型的
extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。记住,下列语句:
extern int a;
仅仅是一个变量的声明,其并不是在定义变量a,并未为a分配内存空间。变量a在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。
通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A编译生成的目标代码中找到此函数。
与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。

(2) 被extern "C"修饰的变量和函数是按照C语言方式编译和连接的


2、explicit构造函数的作用

explicit构造函数是用来防止隐式转换的。请看下面的代码:

class Test1
{
public:
    Test1(int n)
    {
        num=n;
    }//普通构造函数
private:
    int num;
};
class Test2
{
public:
    explicit Test2(int n)
    {
        num=n;
    }//explicit(显式)构造函数
private:
    int num;
};
int main()
{
    Test1 t1=12;//隐式调用其构造函数,成功
    Test2 t2=12;//编译错误,不能隐式调用其构造函数
    Test2 t2(12);//显式调用成功
    return 0;
}

Test1的构造函数带一个int型的参数,代码23行会隐式转换成调用Test1的这个构造函数。而Test2的构造函数被声明为explicit(显式),这表示不能通过隐式转换来调用这个构造函数,因此代码24行会出现编译错误。
普通构造函数能够被隐式调用。而explicit构造函数只能被显式调用。


3、auto_ptr智能指针

(1)、 auto_ptr的意义 
 std::auto_ptr是C++标准库里面的模版类, 属于智能指针
 当系统异常退出的时候避免资源泄漏(内存)。 其他的资源还对应其他的智能指针。  
(2)、 auto_ptr的使用 
std::auto_ptr<int> test(new int(1)); 
test将是一个auto_ptr的对象,使用一个int指针进行初始化。 
test可以象其他指针一样使用,如使用* 使用->但是++不可以使用,以后也许会扩展,其实难对++做越界管理,也许可以放弃一些速度。  
当使用auto_ptr的时候,必须使用显式的类型转化来初始化,如auto_ptr<classA> a(new classA) 
而不能使用auto_ptr<classA> a = new classA;  
(3)、auto_ptr所有权的转移 
auto_ptr对所有权有严格的约定,一个auto_ptr只能控制一个指针,不能控制多个,当auto_ptr拥有一个指针的时候就不能在拥有其他的指针了。同时,不同的auto_ptr不能拥有同一个指针。

智能指针实质是一个栈对象,而并非指针类型。C++的auto_ptr的作用是动态分配对象以及当对象不再需要时自动执行清理。
使用std::auto_ptr,要#include <memory>。
(1)尽量不要使用“operator=”(如果使用了,请不要再使用先前对象)。

(2)记住release()函数不会释放对象,仅仅归还所有权。

(3)std::auto_ptr最好不要当成参数传递(读者可以自行写代码确定为什么不能)。

(4)auto_ptr存储的指针应该为NULL或者指向动态分配的内存块。

(5)auto_ptr存储的指针应该指向单一物件(是new出来的,而不是new[]出来的)。auto_ptr不能指向数组,因为auto_ptr在析构的时候只是调用delete,而数组应该要调用delete[]。

(6)使用auto_ptr作为成员变量,以避免资源泄漏。
(7)auto_ptr不能共享所有权,即不要让两个auto_ptr指向同一个对象。
(8)auto_ptr不能作为容器对象,STL容器中的元素经常要支持拷贝,赋值等操作,在这过程中auto_ptr会传递所有权,那么source与sink元素之间就不等价了。

4、构造函数的初始化列表

常量成员和引用成员自然是要初始化的,问题就在这static成员。
static成员是不允许在类内初始化的,除了const,那么static const 成员是不是在初始化列表中呢?
答案是NO
一是static属于类,它在未实例化的时候就已经存在了,而构造函数的初始化列表嘞,只有在实例化的时候才执行。
二是static成员不属于对象。我们在调用构造函数自然是创建对象,一个跟对象没直接关系的成员要它做什么呢
还有一个问题就是上面那个仁兄说的, .需要初始化的数据成员是对象(继承时调用基类构造函数) ;这个显然是不对的。下面代码能够很好说明了这个问题。c需要初始化不是因为它是类对象,是因为他的成员有引用。
class A {
private:
   int a;
};
class B : public A {
private:
     int aa;
public:
  B(int i ):aa(i),b(9){};
     const int b;
     A c;
};
总结:
static 修饰的变量在类外初始化,const修饰的在参数列表初始化
在构造函数中需要初始化列表初始化的有如下三种情况 
1.带有const修饰的类成员 ,如constinta ;
2.引用成员数据,如 int& p;
3.带有引用的类变量(如题目的对象c)

5、函数模板和类模板
函数模板的实例化是由编译程序在处理函数调用时自动完成的
类模板的实例化必须由程序员在程序中显式地指定
函数模板针对仅参数类型不同的函数
类模板针对仅数据成员和成员函数类型不同的类
6、类的静态成员和非静态成员
(1)、数据成员可以分静态变量非静态变量两种.
静态成员:静态类中的成员加入static修饰符,即是静态成员.可以直接使用类名+静态成员名访问此静态成员,因为静态成员存在于内存,非静态成员需要实例化才会分配内存,所以静态成员不能访问非静态的成员..因为静态成员存在于内存,所以非静态成员可以直接访问类中静态的成员.静态成员在每个类中只有一个拷贝,是解决同一个类的不同对象之间数据和函数共享问题的。
 非成静态员:所有没有加Static的成员都是非静态成员,当类被实例化之后,可以通过实例化的类名进行访问..非静态成员的生存期决定于该类的生存期..而静态成员则不存在生存期的概念,因为静态成员始终驻留在内容中.

 一个类中也可以包含静态成员和非静态成员,类中也包括静态构造函数和非静态构造函数..

(2)、

静态成员函数可以直接引用该类的静态数据成员和静态成员函数,但不能直接引用非静态数据成员和非静态成员函数,否则编译报错。如果要引用,必须通过参数传递的方式得到对象名,然后再通过对象名引用


 
 

区别:
访问方式不一样.静态成员(通过类名.静态成员名访问).非静态成员(通过对象名.非静态成员名访问)
静态成员属于类.该类的所有对象共同拥有这一个成员.
非静态成员属于对象,每个对象都有一份.静态成员不论有类有多少个对象.只在内存中分配一块空间.

7、运算符

& 按位与运算,如:1010 & 1100 = 1000
| 按位或运算,如:1010 & 1100 = 1110
~ 非运算,如:a = 1010; ~a = 0101
<<左移,如:1110 << 1 = 1100
>>右移,如:1000 >> 1 = 0100

8、递归
#include <stdio.h>
int cnt=0;
int fib( int n){
  cnt++;
   if (n==0) 
     return 1; 
   else if (n==1) 
     return 2; 
   else 
     return fib(n-1)+fib(n-2);
}
void main()
{
  fib(8);
   printf ( "%d" ,cnt);
}
==》67

9、
C89支持无返回类型的函数,默认返回int型
C99开始必须要有返回值

可重载的操作符

 输入和输出操作符;算术操作符;关系操作符; 赋值操作符和符合赋值操作符下标操作符;成员访问操作符;引用操作符(*)和箭头操作符(->)自增操作符和自减操作符;调用操作符和函数对象

 其实除了上面说的,还有很多可重载:

  逻辑操作

位操作符;

new/delete操作;

而不可操作的操作符比较少,可直接列出来:

       作用域操作符:::

        条件操作符:?:

        点操作符:.

         指向成员操作的指针操作符:->*.*

        预处理符号:#





  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值