1. malloc在生产自定义类型时,里面的成员变量的空间需要单独处理吗??
struct buffertest {
char strbuffer1[8];
char strbuffer2[8];
char strbuffer3[8];
};
当你使用malloc来创建一个buffertest类型的结构体时,malloc会分配buffertest所需的空间(即24字节),并返回一个指向该内存区域的指针。
malloc(sizeof(buffertest))
会为 buffertest
类型的结构体分配 24 字节的内存空间,其中:
strbuffer1
会占用前 8 字节。strbuffer2
会占用接下来的 8 字节。strbuffer3
会占用最后的 8 字节。
虽然结构体本身被分配了内存,但结构体的成员变量(strbuffer1
、strbuffer2
、strbuffer3
)并不是单独的内存块,而是直接位于结构体分配的内存空间中的。换句话说,malloc
分配了 24 字节的连续内存空间,结构体的成员变量分别占据了这些空间的不同部分。
typedef struct {
char* name; // 字符串的指针
int age;
} Person;
当你使用 malloc
来分配 Person
类型的内存时,malloc
只会为整个结构体本身分配内存。它并不会为 name
这个指针指向的字符串分配内存空间,而是仅仅为 name
指针本身分配内存空间(即指针变量的内存)。至于 name
所指向的字符串,你需要单独为它分配内存。
2. 下面关于C++缺省函数描述错误的是:CD
A.缺省参数是声明或定义函数时为函数的参数指定一个默认值.
B.在调用有缺省参数的函数时,如果没有指定实参则采用该默认值,否则使用指定的实参
C.C和C++都支持缺省参数
D.全缺省就是参数全部给缺省值,半缺省就是缺省一半的值
C:纯C语言,即.c文件,函数不支持缺省参数,C++即.cpp文件支持
D:半缺省不能随便缺省一半,必须从右往左缺省,否则编译出错
3. 指针通过某一个指针变量指向一个对象后,他所指向的变量间接操作。程序中使用指针程序的可读性差,而引用本身就是目标变量别名,对引用的操作就是对目标变量的操作。
4. 关于C++的inline关键字,以下说法正确的是:C
A.使用inline关键字的函数会被编译器在调用处展开
B.头文件中可以包含inline函数的声明
C.可以在同一个项目的不同源文件内定义函数名相同但实现不同的inline函数
D.递归函数也都可以成为inline函数
A.不一定,因为inline只是一种建议,需要看此函数是否能够成为内联函数
B. inline函数不支持声明和定义分离开,因为编译器一旦将一个函数作为内联函数处理,就会在调用位置展开,即该函数是没有地址的,也不能在其他源文件中调用,故一般都是直接在源文件中定义内联函数的
C.inline函数会在调用的地方展开,所以符号表中不会有inline函数的符号名,不存在链接冲突。
D.比较长的函数,递归函数就算定义为inline,也会被编译器忽略,故错误
5. this指针
this指针代表了当前对象,能够区分每一个对象的自身数据。基类公有成员在子类和对象外都可以直接访问,与this无关 。静态成员函数没有this指针,只有非静态成员函数才有,且为隐藏指针。this指针在非静态的成员函数里面,对象不存在。
6. 类的定义
构造函数不能有返回值,包括void类型也不行。
自动生成的缺省拷贝构造函数,作为该类的公有成员,否则无法进行默认的拷贝构造
7. 构造函数和析构函数
与++a等效的运算符函数调用形式为:a.operator++()
区分前缀后缀时,后缀运算需要加一个int参数
无参成员函数相当于有一个参数的全局函数,不能是二元运算符
8. 构造函数初始化列表
static const char* d 是静态成员,只能在类外初始化
静态变量也可以是自定义类型的变量
static成员变量在对象生成之前生成
static函数唯一能够访问的就是static变量或者其他static函数
友元函数不具备this指针,更谈不上this调用
9. 下面有关c++内存分配堆栈说法错误的是( D )
A.对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制
B. 对于栈来讲,生长方向是向下的,也就是向着内存地址减小的方向;对于堆来讲,它的生长方向是向上的,是向着内存地址增加的方向增长
C.对于堆来讲,频繁的 new/delete 势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题
D.一般来讲在 32 位系统下,堆内存可以达到4G的空间,但是对于栈来讲,一般都是有一定的空间大小的
A.栈区主要存在局部变量和函数参数,其空间的管理由编译器自动完成,无需手动控制,堆区是自己申请的空间,在不需 要时需要手动释放
B.栈区先定义的变量放到栈底,地址高,后定义的变量放到栈顶,地址低,因此是向下生长的,堆区则相反
C.频繁的申请空间和释放空间,容易造成内存碎片,甚至内存泄漏,栈区由于是自动管理,不存在此问题
10.
ClassA *pclassa=new ClassA[5];
delete pclassa;
c++语言中,类ClassA的构造函数和析构函数的执行次数分别为( )
A.5,1
B.1,1
C.5,5
D.程序可能崩溃
A.申请对象数组,会调用构造函数5次,delete由于没有使用[],此时只会调用一次析构函数,但往往会引发程序崩溃
B.构造函数会调用5次
C.析构函数此时只会调用1次,要想完整释放数组空间,需要使用[]
D.正确
11. 使用 char* p = new char[100]申请一段内存,然后使用delete p释放,有什么问题?( B )
A.会有内存泄露
B.不会有内存泄露,但不建议用
C.编译就会报错,必须使用delete []p
D.编译没问题,运行会直接崩溃
A.对于内置类型,此时delete就相当于free,因此不会造成内存泄漏
B.正确
C.编译不会报错,建议针对数组释放使用delete[],如果是自定义类型,不使用方括号就会运行时错误
D.对于内置类型,程序不会崩溃,但不建议这样使用
12. 下面有关C++中为什么用模板类的原因,描述错误的是? ( C )
A.可用来创建动态增长和减小的数据结构
B.它是类型无关的,因此具有很高的可复用性
C.它运行时检查数据类型,保证了类型安全
D.它是平台无关的,可移植性
A.模板可以具有非类型参数,用于指定大小,可以根据指定的大小创建动态结构
B.模板最重要的一点就是类型无关,提高了代码复用性
C.模板运行时不检查数据类型,也不保证类型安全,相当于类型的宏替换,故错误
D.只要支持模板语法,模板的代码就是可移植的
类模版中的成员函数全是模版函数
模板类是一个家族,编译器的处理会分别进行两次编译,其处理过程跟普通类不一样
13. T是一个数据类型,在vs系列编译器中,debug模式下,关于std::vector::at 和 std::vector::operator[] 描述正确的是( C )
A.at总是做边界检查, operator[] 不做边界检查.
B.at 不做边界检查, operator[] 做边界检查.
C.at和operator[] 都是会做边界检查的
D.以上都不对
注意题目专门强调了vs系列编译器,debug模式下
at() 和 operator[] 都是根据下标获取任意位置元素的,在debug模式下两者都会去做边界检查。
当发生越界行为时,at 是抛异常,operator[] 内部的assert会触发
故选择C
14 迭代器
vector的插入操作如果导致底层空间重新开辟,则迭代器就会失效。如果空间足够,不扩容时,迭代器不一定失效,比如push_back尾插,元素插入到空间末尾,在不扩容时不会对迭代器产生影响
vector的删除操作不光会导致指向被删除元素的迭代器失效,删除元素后面的迭代器也会失效
15 STL中的priority_queue使用的底层数据结构是什么( ):优先级队列priority_queue底层采用vector容器作为底层数据结构
16. 下面关于访问权限与继承权限说法不正确的是( )
A.访问权限和继承权限是不同的概念
B.访问权限和继承权限关键字上是一样的,但是出现位置不一样
C.如果是protected继承方式,基类public的成员变量能通过基类对象在类外直接访问
D.基类私有的成员变量在子类中都不能直接访问,因为没有被子类继承了
A.两个权限控制的东西不一样
B.访问权限在类内部,继承权限在类外
C.只要是public成员对象都可以直接访问
D.基类私有成员不能直接访问不是没有被继承,而是权限问题
下面代码输出结果:( )
class A
{
public:
void f(){ cout<<"A::f()"<<endl; }
int a;
};
class B : public A
{
public:
void f(int a){cout<<"B::f()"<<endl;}
int a;
};
int main()
{
B b;
b.f();
return 0;
}
不能通过编译是正确的,不过原因不是因为成员变量a的问题,而是子类同名隐藏了父类方法的原因
17. 关于基类与派生类对象模型说法正确的是()
A.基类对象中包含了所有基类的成员变量
B.子类对象中不仅包含了所有基类成员变量,也包含了所有子类成员变量
C.子类对象中没有包含基类的私有成员
D.基类的静态成员可以不包含在子类对象中
E.以上说法都不对
A.静态变量就不被包含
B.同理,静态变量就不被包含
C.父类所有成员都要被继承,因此包含了
D.静态成员一定是不被包含在对象中的
E.很显然,以上说法都不正确
18. 下列说法正确的是()
A.set中的某个元素值不能被直接修改
B.map和unordered_map都是C++11提供的关联式容器
C.因为map和set的底层数据结构相同,因此在实现时set底层实际存储的是<key, key>的键值对
D.map和multimap中都重载了[]运算符
A:正确,因为set要保证其有序,因此set中元素不能被直接修改,若要修改可以先删除,在插入
B:错误,map是C++98中已存在的,unordered_map是C++11中才有的
C:错误,map和set底层结构都是红黑树,而其底层红黑树在实现时并没有区分是存k模型还是KV 模型
D:错误,map中key是唯一的,每个key都有与之对应的value,经常需要通过key获取value,因此 map为了形象简 单重载了[]运算符, multimap中key是可以重复的,如果重载了[]运算符,给定 一个key时,就没有办法返回 value了,因此,multimap中没有重载[]运算符
19. 关于AVL树的旋转说法正确的是()
A.插入时,AVL树最多只需要旋转两次
B.删除时,只要某个节点的平衡因子不满足特性时 ,只需要对该棵子树进行旋转,就可以使AVL树再次平衡
C.AVL树的节点中必须维护平衡因子,因为要依靠其平衡因子是否需要旋转以维护其平衡性
D.AVL树的双旋转只需要直接使用对应的单旋转即可
A:正确,即双旋
B:错误,可能需要旋转多次,子树旋转后,其高度降低了一层,其上层可能也需要跟着旋转
C:错误,平衡因子不是必须要维护的,在操作时也可以直接通过高度函数来算,只不过比较麻烦
D:错误,不能直接使用单旋转,因为两个单旋转完成后,还需要对部分节点的平衡因子进行更新
红黑树是近似的平衡树,没有什么最坏情况,插入的时间复杂度为O(log(N))
要使哈希高效:选择好的哈希函数非常关键
好的哈希函数可以减少发生冲突的概率
万一发生冲突,好的处理好戏冲突的方法也比较关键,否则冲突处理不当,也会增加后序元素冲 突的概率
哈希函数设计原则:
1. 哈希函数应该尽可能简单
2. 哈希函数的值域必须在哈希表格的范围之内
3. 哈希函数的值域应该尽可能均匀分布,即取每个位置应该是等概率的
冲突越多,查找时比较的次数就越多,对平均查找长度影响比较大。
21. 下面关于列表初始化说法正确的是()
A.C++语言从C++98开始,就支持列表方式的初始化
B.列表初始化没有什么实际作用,直接调用对应的构造函数就可以了
C.自定义类型可以支持多个对象初始化,只需要增加initializer_list类型的构造函数即可
D.以下关于c和d的初始化,结果完全相同 // short c = 65535; short d { 65535 };
A:错误,列表初始化是从C++11才开始支持的
B:错误,列表初始化可以在定义变量时就直接给出初始化,非常方便
C:正确
D:错误,不同,列表初始化在初始化时,如果出现类型截断,是会报警告或者错误的
final 只能修饰派送类的虚函数
有时捕获异常并不是为了处理异常,而是要做一些其他事情,做完后需要将异常重新抛 出,交给该异常的 处理位置去处理
weak_ptr不能单独管理资源,必须配合shared_ptr一块使用,解决shared_ptr中存在的 循环引用问题
C++11中提供的智能指针都只能管理单个对象的资源,没有提供管理一段空间资源的智 能指针
weak_ptr和shared_ptr都是通过引用计数实现,但是在底层还是有区别的