您的位置:首页 > 编程语言 > C语言/C++

C++知识小记

2016-03-05 22:02 302 查看
C++中const有什么用?

  不要一听到const就说是常量,这样给考官一种在和一个外行交谈的感觉。应该说const修饰的内容不可改变就行了, 定义常量只是一种使用方式而已,还有const数据成员,const参数, const返回值, const成员函数等, 被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。

★ 相同点:

 

    1. 都是地址的概念;

       指针指向一块内存,它的内容是所指内存的地址;

       引用是某块内存的别名。

 

    ★ 区别:

 

    1. 指针是一个实体,而引用仅是个别名;

    2. 引用使用时无需解引用(*),指针需要解引用;

    3. 引用只能在定义时被初始化一次,之后不可变;指针可变;

       引用“从一而终” ^_^

    4. 引用没有 const,指针有 const,const 的指针不可变;

    5. 引用不能为空,指针可以为空;

    6. “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小;

    typeid(T) == typeid(T&) 恒为真,sizeof(T) == sizeof(T&) 恒为真,但是当引用作为类成员名称时,其占用空间与指针相同4个字节(没找到标准的规定)。

    7. 指针和引用的自增(++)运算意义不一样;

1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在,如全局变量,static变量。

  2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

  3)从堆上分配(动态内存分配)程序在运行的时候用malloc或new申请任意多少的内存,程序员负责在何时用free或delete释放内存。动态内存的生存期自己决定,使用非常灵活。

什么是动态特性?

  在绝大多数情况下, 程序的功能是在编译的时候就确定下来的, 我们称之为静态特性。 反之, 如果程序的功能是在运行时刻才能确定下来的, 则称之为动态特性。C++中, 虚函数,抽象基类, 动态绑定和多态构成了出色的动态特性。

 什么是深浅拷贝?

  浅拷贝是创建了一个对象用一个现成的对象初始化它的时候只是复制了成员(简单赋值)而没有拷贝分配给成员的资源(如给其指针变量成员分配了动态内存); 深拷贝是当一个对象创建时,如果分配了资源,就需要定义自己的拷贝构造函数,使之不但拷贝成员也拷贝分配给它的资源。

野指针

答:“野指针”是很危险的,if语句对它不起作用。“野指针”的成因主要有两种:

(1)指针变量没有被初始化。指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。

char *p = NULL;      char *str = (char *) malloc(100);

(2)指针p被free或者delete之后,没有置为NULL

(3)指针操作超越了变量的作用范围。所指向的内存值对象生命期已经被销毁

指针和引用有什么分别;

答:引用必须初始化,即引用到一个有效的对象;而指针在定义的时候不必初始化,

可以在定义后面的任何地方重新赋值。

引用初始化后不能改变,指针可以改变所指的对象

不存在指向NULL的引用,但存在指向NULL的指针

引用的创建和销毁并不会调用类的拷贝构造函数

语言层面,引用的用法和对象一样;在二进制层面,引用一般都是通过指针来实现的,

只不过编译器帮我们完成了转换.引用既具有指针的效率,又具有变量使用的方便性和直观性.

C++中的Const用法

答:char * const p;    // 指针不可改,也就说指针只能指向一个地址,不能更改为其他地址,修饰指针本身

char const * p;   // 所指内容不可改,也就是说*p是常量字符串,修饰指针所指向的变量

const char * const p 和 char const * const p; // 内容和指针都不能改

const修饰函数参数是它最广泛的一种用途,它表示函数体中不能修改参数的值,

传递过来的参数在函数内不可以改变,参数指针所指内容为常量不可变,参数指针本身为常量不可变

在引用或者指针参数的时候使用const限制是有意义的,而对于值传递的参数使用const则没有意义

const修饰类对象表示该对象为常量对象,其中的任何成员都不能被修改。

const修饰的对象,该对象的任何非const成员函数都不能被调用,因为任何非const成员函数会有修改成员变量的企图。

const修饰类的成员变量,表示成员常量,不能被修改,同时它只能在初始化列表中赋值。static const 的成员需在声明的地方直接初始。

const修饰类的成员函数,则该成员函数不能修改类中任何非const成员。一般写在函数的最后来修饰。

在函数实现部分也要带const关键字.

对于const类对象/指针/引用,只能调用类的const成员函数,因此,const修饰成员函数的最重要作用就是限制对于const对象的使用

使用const的一些建议:在参数中使用const应该使用引用或指针,而不是一般的对象实例

const在成员函数中的三种用法(参数、返回值、函数)要很好的使用;

const在成员函数中的三种用法(参数、返回值、函数)要很好的使用;

不要轻易的将函数的返回值类型定为const;除了重载操作符外一般不要将返回值类型定为对某个对象的const引用;

const常量与define宏定义的区别

答:(1) 编译器处理方式不同。define宏是在预处理阶段展开,生命周期止于编译期。

只是一个常数、一个命令中的参数,没有实际的存在。

#define常量存在于程序的代码段。const常量是编译运行阶段使用,const常量存在于程序的数据段.

(2)类型和安全检查不同。define宏没有类型,不做任何类型检查,仅仅是展开。

const常量有具体的类型,在编译阶段会执行类型检查。

(3) 存储方式不同。define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。

解释堆和栈的区别

答:1、栈区(stack)— 由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

由系统自动分配。声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间 。

只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。

在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域,栈的大小是2M。

如果申请的空间超过栈的剩余空间时,将提示overflow。

栈由系统自动分配,速度较快。但程序员是无法控制的。

函数调用时,第一个进栈的是主函数中后的下一条指令,的地址,然后是函数的各个参数。

在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。

堆区(heap) — 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收 。

注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,需要程序员自己申请,并指明大小,在c中malloc函数

在C++中用new运算符。首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,

另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

堆是向高地址扩展的数据结构,是不连续的内存区域。而链表的遍历方向是由低地址向高地址。

堆的大小受限于计算机系统中有效的虚拟内存。

堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便

一般是在堆的头部用一个字节存放堆的大小

C++的空类,默认产生哪些类成员函数?

答:class Empty

 public:

Empty();                           //缺省构造函数

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

~Empty();                          //虚构函数

Empty& operator(const Empty& )     //赋值运算符

Empty& operator&();               //取址运算符

const Empty* operator&() const;   // 取址运算符 const

谈谈类和结构体的区别

答:结构体在默认情况下的成员都是public的,而类在默认情况下的成员是private的。结构体和类都必须使用new创建,

struct保证成员按照声明顺序在内存在存储,而类不保证。

什么是预编译,何时需要预编译

答:就是指程序执行前的一些预处理工作,主要指#表示的.

需要预编译的情况:总是使用不经常改动的大型代码体。所有模块都使用一组标准的包含文件和相同的编译选项。

资源:进程是拥有资源的一个独立单位,线程是不拥有资源。

调度:线程作为调度和分配的基本单位,进程是作为资源的基本单位

并发性:进程之间可以有并发性进行,同一个进程中的多个线程是可以并发执行

系统开销:进程在创建和撤销的时候,由于系统要分配和回收资源,导致系统的开销明显大于线程

一个进程可以拥有多个线程。

C++中哪些函数不能被声明为虚函数?

答:普通函数(非成员函数),构造函数,内联成员函数、静态成员函数、友元函数。

(1)虚函数用于基类和派生类,普通函数所以不能

(2)构造函数不能是因为虚函数采用的是虚调用的方法,允许在只知道部分信息的情况的工作机制,

特别允许调用只知道接口而不知道对象的准确类型的方法,但是调用构造函数即使要创建一个对象,

那势必要知道对象的准确类型。

(3)内联成员函数的实质是在调用的地方直接将代码扩展开

(4)继承时,静态成员函数是不能被继承的,它只属于一个类,因为也不存在动态联编等

(5)友元函数不是类的成员函数,因此也不能被继承

关键字static的作用是什么?

这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用:
1). 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
2). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。

比如:在文件ClassA.cpp中声明  static   int    g_id=0,那么g_id就不能被ClassB.cpp定义的函数使用。

3). 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。
大多数应试者能正确回答第一部分,一部分能正确回答第二部分,同是很少的人能懂得第三部分。这是一个应试者的严重的缺点,因为他显然不懂得本地化数
据和代码范围的好处和重要性。

头文件中的ifndef/define/endif有什么作用?
答:这是C++预编译头文件保护符,保证即使文件被多次包含,头文件也只定义一次。

#include<file.h> 与 #include "file.h"的区别?
答:前者是从标准库路径寻找和引用file.h,而后者是从当前工作路径搜寻并引用file.h。

sizeof计算的是在栈中分配的内存大小。
(1) sizeof不计算static变量占得内存;
(2) 指针的大小一定是4个字节,而不管是什么类型的指针;
(3) char型占1个字节,int占4个字节,short int占2个字节
long int占4个字节,float占4字节,double占8字节,string占4字节

sizeof与strlen的区别?
答: (1)sizeof的返回值类型为size_t(unsigned int);
(2)sizeof是运算符,而strlen是函数;
(3)sizeof可以用类型做参数,其参数可以是任意类型的或者是变量、函数,而strlen只能用char*做参数,且必须是以’\0’结尾;
(4)数组作sizeof的参数时不会退化为指针,而传递给strlen是就退化为指针;
(5)sizeo是编译时的常量,而strlen要到运行时才会计算出来,且是字符串中字符的个数而不是内存大小;
20.

C++中有malloc/free,为什么还有new/delete?
答:malloc/free是C/C++标准库函数,new/delete是C++运算符。他们都可以用于动态申请和释放内存。
对于内置类型数据而言,二者没有多大区别。malloc申请内存的时候要制定分配内存的字节数,而且不会做初始化;new申请的时候有默认的初始化,同时可以指定初始化;
对于类类型的对象而言,用malloc/free无法满足要求的。对象在创建的时候要自动执行构造函数,消亡之前要调用析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制之内,不能把执行构造函数和析构函数的任务强加给它,因此,C++还需要new/delete。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: