c++基础常考题

c++基础常考题

new delete malloc free的关系



malloc free是库函数,对于非内部数据结构的对象而言,无法调用构造函数和析构函数。
newdelete是运算符,在编译器控制权限之内,因此在创建对象的时候,可以自动执行构造函数,满足c++动态内存分配和初始化工作,以及能清理和释放内存工作。

delete 和delete[] 的区别

newnew []对应,delete调用对象的析构函数,delete[]调用每一个数组对象的析构函数;
对于一个基本数据类型来说,都一样,deletedelete[]都一样(int *a = new int; *a = 5;delete a; delete []a;)

继承的优缺点

类继承是在编译时刻静态定义的,且可以直接使用,类继承可以较方便地改变父类的实现。但是类继承也有一些不足之处。
首先,因为继承在编译时刻就定义了,所以无法再运行时刻改变从父类继承的实现。更糟糕的是,父类通常
至少定义了子类的部分行为,父类的任何改变都有可能改变子类的行为。如果继承下来的实现不适合解决
新的问题,则父类必须重写或者被其他合适的类换掉。这种依赖关系限制了灵活性并最终限制了复用性

子类析构时要调用父类的析构函数吗?

首先调用继承类的析构函数,再调用父类的析构函数。[通过virtual,需要想到菱形继承,从而避免内存泄露和多次析构]
    构造函数的顺序也要清楚

多态、虚函数和纯虚函数

如何查看一个数的二进制里有多少个1?

Java无析构函数和深拷贝,浅拷贝

什么是引用?申明和使用引用要注意什么问题?

引用就是某个目标变量的别名,对引用的操作和对变量直接操作效果完全相同。
声明一个引用的时候,必须对它进行初始化。(int a = 5;int &reference = a;)
不能把该引用名作为其他变量名的别名。声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量的别名,它本身不是一种数据类型,因此引用本身不占存储空间,系统也不给引用分配存储单元。不能建立数组的引用。

将引用作为函数参数有哪些特点?

传递引用和指针在当做函数参数时,作用是一样的;
使用引用传递函数的参数,在内存中并没有实参的副本,而一般变量传递参数时,需要。因此,当参数传递的数据较大时,
用引用比用按值传递的效率和所占空间都好;
使用指针传递,虽然效果也一样,但是在被调用函数中,同样要给形参分配存储单元,且需要重复使用“*变量名”的形式进行运算,这很容易产生错误,程序可读性差;另一方面,在主调函数的调用出,必须用变量的地址作为实参。而引用更容易使用,更清晰。

什么时候使用const引用?

如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应该使用常引用。

将引用作为函数返回值类型的格式、好处和需要遵守的规则是?

好处:在内存中不需要被返回值的副本;(注意:正是因为这一点,所以不可以返回函数中的局部变量)


----------


注意:

 1. 不能返回局部变量的引用;
 2. 不能返回函数内部new分配的内存的引用;

 【解释】C\C++为什么不能返回函数内部new分配的内存的引用?

可以的 但是作为引用返回的变量必须是静态变量或者是全局变量 或者是传入的引用参数
即作用域在退出函数后依然有效
下面是几种可行的方式

char *& alloc(char * &pa)
{
    pa = new char [10];
    return pa;
}
//引用参数 并返回

char * va;
char *& alloc()
{
    va = new char [10];
    return va;
}
//全局变量

char *& alloc()
{
    static char * va = new char [120];
    return va;
}
//静态变量

下面是错误的做法
char *&alloc()
{
    char *va = new char [100];
    return va;
}//va为局部变量 在返回后释放 对返回值操作会有不可预知后果
追问
char *&alloc(){    char *va = new char [100];    return va;}//va为局部变量 在返回后释放 对返回值操作会有不可预知后果
还是可以正常运行的,退出函数时,它只是释放va,而没有释放va指向的内存吧?它底层是如何执行的,va的地址在退出函数时,其实并没变不是吗?
追答
char *&alloc(){    char *va = new char [100];    return va;}

对于这样的程序 执行过程为
进入函数alloc
为变量va分配内存 假设为0x12345678 大小为四个字节 (32位机指针)
执行new操作 在内存0x12345678地址存入申请到的内存地址 假设为0x45670abc
也就是说 *(0x12345678)=0x45670abc
以上部分应该很好理解
然后返回va 也就是返回上一层一个值 这个值不可能是悬空的 它需要一个地址来存 由于是引用返回,所以返回的地址实际上就是变量va的地址0x12345678
退出函数 释放临时变量 包括va的地址0x12345678

返回到主调函数,使用返回值 比如赋值 a=alloc(); 相当于执行操作
a=*(0x12345678) 注意 在上一步 这个地址已经被释放了 所以当前这个地址存的是什么东西是不确定的 可能还是0x45670abc 也可能已经有了变化
这样a的值就不一定是你需要的了 结果也就可能是错的

关键在于退出函数 释放内存 使用内存这步 先释放 后使用 于是出错

如果是全局/静态变量 自然不会有这个问题 因为内存依旧被原来变量占用 类似引用做参数也是同样的效果

#include 
using namespace std;
string& foo()
{
    string* str = new string("abc");
    return *str; 
}
int main()
{
    string b = foo(); //string str = foo(); 显然new生成的这块内存将无法释放。
    /*
    string& tmp = foo();
    string str = tmp; 
    delete &tmp;
    */
    //http://blog.csdn.net/why_ny/article/details/7901670 这个也是需要好好看一下的 
    cout<
  1. 可以返回类成员的引用,但最好是const;
  2. 流操作符重载返回值声明为引用的作用是什么?
    << >>这两个符号;
    cout<<”hello”<

引用与多态的关系?

引用是除了指针外,另一种可以产生多态效果的手段,这意味着,一个基类的引用可以指向它的派生类实例。例如

Class A;
Class B:A;
B b;
A & ref =b;

引用与指针的区别是什么?

指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;引用本身就是目标变量的别名,对引用的操作就是对目标变量的别名。

什么时候需要引用?

流操作符<<,>>、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符的参数、都推荐用引用。

define

#define DOUBLE(X) X+X
i = 5*DOUBLE(5);
i是多少?
//25;
#include 
using namespace std;
class A{
};

int main()
{
    cout<<sizeof(A)<// 1bytes, 8bits.
}

你可能感兴趣的:(C++)