C++练习 —— 命名空间、引用、类的定义、构造函数和析构函数、运算符重载、const成员函数、类相关OJ题
目录
一、C++ | 命名空间
二、C++ | 引用
三、C++ | 类的定义
四、C++ | 构造函数和析构函数
五、C++ | 运算符重载
六、C++ | const成员函数
七、C++ | 类相关OJ题
一、C++ | 命名空间
1、下面关于C++命名空间描述错误的是(C )
A.命名空间定义了一个新的作用域。
B.std是C++标准库的命名空间。
C.在C++程序中,命名空间必须写成using namespace std;
D.我们可以自己定义命名空间。
解析:
A.命名空间主要解决名字冲突,其作用就是定义一个新的作用域
B.std是标准命名空间
C.还有std::xx 和using std::xx来使用标准库中的用法,所以不是必须写using namespace std
D.可以通过namespace space_name{};定义自己新的命名空间
2、下面关于C++缺省参数描述错误的是( CD) 【不定项缺省】
A.缺省参数是声明或定义函数时为函数的参数指定一个默认值.
B.在调用有缺省参数的函数时,如果没有指定实参则采用该默认值,否则使用指定的实参
C.C和C++都支持缺省参数
D.全缺省就是参数全部给缺省值,半缺省就是缺省一半的值
解析:
A.缺省参数就是给出的函数参数的默认值
B.很明显,这是给出缺省值的意义所在
C.纯C语言,即.c文件,函数不支持缺省参数,C++即.cpp文件支持
D.半缺省不能随便缺省一半,必须从右往左缺省,否则编译出错
3、以下不是double compare(int,int)的重载函数的是( D)
A.int compare(double,double)
B.double compare(double,double)
C.double compare(double,int)
D.int compare(int,int)
解析:
A.重载必须是参数列表有所不同(包括个数和类型),所以参数类型不同,构成重载
B.参数类型不同,构成重载
C.参数类型不同,构成重载
D.函数重载不能依靠返回值的不同来构成重载,因为调用时无法根据参数列表确定调用哪个重载函数,故错误
4、下面关于函数重载描述错误的是(ABD )【多选择】
A.构成函数重载的条件是函数名相同就可以
B.重载的函数参数可以相同
C.重载的函数返回值可以相同
D.C和C++都支持函数重载
解析:
A.函数名相同只是函数重载的条件之一
B.重载函数必须参数列表有所不同(包括参数类型和参数个数)
C.重载函数不依靠返回值来区分,所以返回值可以相同
D.C不支持函数重载
二、C++ | 引用
1、关于引用以下说法错误的是(E )。(阿里巴巴2015笔试题)
A.引用必须初始化,指针不必
B.引用初始化以后不能被改变,指针可以改变所指的对象
C.不存在指向空值的引用,但是存在指向空值的指针
D.一个引用可以看作是某个变量的一个“别名”
E.引用传值,指针传地址
F.函数参数可以声明为引用或指针类型
解析:
A.引用必须初始化,必须在定义引用时明确引用的是哪个变量或者对象,否则语法错误,指针不初始化时值为随机指向
B.引用一旦定义时初始化指定,就不能再修改,指针可以改变指向
C.引用必须出示化,不能出现空引用,指针可以赋值为空
D.简单粗暴的引用理解可以理解为被引用变量或对象的"别名"
E.引用表面好像是传值,其本质也是传地址,只是这个工作有编译器来做,所以错误
F.函数调用为了提高效率,常使用引用或指针作为函数参数传递变量或对象
2、“引用”与指针的区别是什么( A)
A.指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作
B.引用通过某个引用变量指向一个对象后,对它所指向的变量间接操作。程序中使用引用,程序的可读性差;而指针本身就是目标变量的别名,对指针的操作就是对目标变量的操作
C.指针比引用更节省存储空间 D.以上都不正确
解析:
A.指针是间接操作对象,引用时对象的别名,对别名的操作就是对真实对象的直接操作,故正确
B.很显然,答案刚好相反
C.指针需要开辟空间,引用不需要开辟空间,故错误
D.一山不容二虎,A正确,D如何是好
3、关于引用与指针的区别,下面叙述错误的是( B)
A.引用必须被初始化,指针不必
B.指针初始化以后不能被改变,引用可以改变所指的对象
C.删除空指针是无害的,不能删除引用
D.不存在指向空值的引用,但是存在指向空值的指针
解析:
A.引用必须定义时初始化,指针不初始化其值为随机指向
B.指针可以改变指向,引用不能,故错误
C.空指针没有任何指向,删除无害,引用是别名,删除引用就删除真实对象
D.引用必须初始化,所以不能为空引用,指针可以
4、在( C)情况下适宜采用 inline 定义内联函数
A.函数体含有循环语句 B.函数体含有递归语句
C.函数代码少、频繁调用 D.函数代码多,不常调用
解析:
A.含有循环语句,违背内联函数的本质
B.含有递归语句,违背内联函数的本质
C.尽可能把代码短小,频繁调用的函数设置为内联函数
D.含代码量大,违背内联函数的本质,内联函数是一种建议,如果函数内部包括循环,递归,或者代码量大且复杂,这些函数即使设置了内联函数,系统也不会当做内联函数来处理。
5、关于c++的inline关键字,以下说法正确的是(C )
A.使用inline关键字的函数会被编译器在调用处展开
B.头文件中可以包含inline函数的声明
C.可以在同一个项目的不同源文件内定义函数名相同但实现不同的inline函数
D.递归函数也都可以成为inline函数
解析:
A.不一定,因为inline只是一种建议,需要看此函数是否能够成为内联函数
B. inline函数不支持声明和定义分离开,因为编译器一旦将一个函数作为内联函数处理,就会在调用位置展开,即该函数是没有地址的,也不能在其他源文件中调用,故一般都是直接在源文件中定义内联函数的
C.inline函数会在调用的地方展开,所以符号表中不会有inline函数的符号名,不存在链接冲突。
D.比较长的函数,递归函数就算定义为inline,也会被编译器忽略,故错误
三、C++ | 类的定义
1、有一个如下的结构体:
struct A
{
long a1;
short a2;
int a3;
int *a4;
};
请问在64位编译器下用sizeof(struct A)计算出的大小是多少?(A )
A.24 B.28 C.16 D.18
解析:
A.首先明确,64位下指针大小为8个字节,这是关键,a1占4字节,a2两字节,由于a3占4字节, a2需要补齐2个字节,对于a1,a2,a3一共开辟了12个字节,由于a4占8个字节,所以a4之后要 补齐4个字节才能是8的整数倍,最后总和为24字节,刚好也是8的倍数,所以最终结构体大小为 24字节,答案A
B.错误 C.如果系统是32位,则结构体大小为16 D.错误
2、在C++中的结构体是否可以有成员函数?(B )
A.不可以,结构类型不支持成员函数 B.可以有 C.不可以,只有类允许有成员函数
解析:
A.C语言结构体不支持成员函数,但C++结构体支持,其class与struct本质没有区别,唯一区别在于默认时class的访问属性为私有,struct为公有 B.正确 C.C++结构体也支持成员函数
3、下面描述错误的是( C)
A.this指针是非静态成员函数的隐含形参. B.每个非静态的成员函数都有一个this指针.
C.this指针是存在对象里面的. D.this指针可以为空
解析:
A.静态成员函数没有this指针,只有非静态成员函数才有,且为隐藏指针
B.非静态成员函数的第一个参数就是隐藏的this指针
C.this指针在非静态的成员函数里面,对象不存在,故错误
D.单纯的对this赋空是不可以的,不过可以强转直接赋空,不过一般不进行这样的操作
四、C++ | 构造函数和析构函数
1、下列关于构造函数的描述正确的是( C)
A.构造函数可以声明返回类型
B.构造函数不可以用private修饰
C.构造函数必须与类名相同
D.构造函数不能带参数
解析:
A.构造函数不能有返回值,包括void类型也不行
B.构造函数可以是私有的,只是这样之后就不能直接实例化对象
C.这是必须的 D.构造函数不光可以带参数,还可以有多个构造函数构成重载
2、假定MyClass为一个类,则该类的拷贝构造函数的声明语句是(C )
A.MyClass(MyClass x) B.MyClass &(MyClass x)
C.MyClass(MyClass &x) D.MyClass(MyClass *x)
解析:
A.参数必须是引用,否则造成无限递归
B.语法错误 C.正确 D.这种写法只是普通的构造函数,不能成为拷贝构造函数
3、在函数F中,本地变量a和b的构造函数(constructor)和析构函数(destructor)的调用顺序是: ( D)
Class A;
Class B;
void F()
{
A a;
B b;
}
A.b构造 a构造 a析构 b析构 B.a构造 a析构 b构造 b析构
C.b构造 a构造 b析构 a析构 D.a构造 b构造 b析构 a析构
解析:
A.构造顺序是按照语句的顺序进行构造,析构是按照构造的相反顺序进行析构,因此先构造b错误
B.a析构的时机不对,对象析构要在生存作用域结束的时候才进行析构,因此先析构a错误
C.b的构造时机错误,先构造a
D.正确,构造顺序是按照语句的顺序进行构造,析构是按照构造的相反顺序进行析构
4、设已经有A,B,C,D4个类的定义,程序中A,B,C,D析构函数调用顺序为?(B )
C c;
int main()
{
A a;
B b;
static D d;
return 0;
}
A.D B A C B.B A D C C.C D B A D.A B D C
解析:
类的析构函数调用一般按照构造函数调用的相反顺序进行调用,但是要注意static对象的存在, 因为static改变了对象的生存作用域,需要等待程序结束时才会析构释放对象,全局对象先于局部对象进行构造,局部对象按照出现的顺序进行构造,无论是否为static,所以构造的顺序为 c a b d,析构的顺序按照构造的相反顺序析构,只需注意static改变对象的生存作用域之后,会放在局部 对象之后进行析构,因此析构顺序为B A D C
5、拷贝构造函数的特点是(D )
A.该函数名同类名,也是一种构造函数,该函数返回自身引用
B.该函数只有一个参数,是对某个对象的引用
C.每个类都必须有一个拷贝初始化构造函数,如果类中没有说明拷贝构造函数,则编译器系统会自动生成一个缺省拷贝构造函数,作为该类的保护成员
D.拷贝初始化构造函数的作用是将一个已知对象的数据成员值拷贝给正在创建的另一个同类的对象
解析:
A.拷贝构造函数也是一构造函数,因此不能有返回值
B.该函数参数是自身类型的对象的引用
C.自动生成的缺省拷贝构造函数,作为该类的公有成员,否则无法进行默认的拷贝构造
D.用对象初始化对象这是拷贝构造函数的使命,故正确
五、C++ | 运算符重载
1、已知表达式++a中的"++"是作为成员函数重载的运算符,则与++a等效的运算符函数调用形式为( A)
A.a.operator++() B.a.operator++(0)
C.a.operator++(int) D.operator++(a,0)
解析:
A.正确 B.operator++()传递了整形参数,故为后置++,错误
C.调用函数传递类型,导致语法错误 D.参数过多,语法错误
2、在重载一个运算符为成员函数时,其参数表中没有任何参数,这说明该运算符是 (C )
A.无操作数的运算符 B.二元运算符
C.前缀一元运算符 D.后缀一元运算符
解析:
A.重载为成员函数时,其函数的参数个数与真实的函数参数个数会减少1个,减少的则通过this指针进行传递,所以无参则说明有一个参数,故错误
B.无参成员函数相当于有一个参数的全局函数,不能是二元运算符
C.正确 D.区分前缀后缀时,后缀运算需要加一个int参数
3、哪个操作符不能被重载 (C )
A.* B.() C.. (点) D.[] E.->
解析:
A.可以,例如重载对象取值,典型有以后学到的智能指针
B.可以,例如以后学到的仿函数就是通过重载()实现的
C.不能,不能被重载的运算符只有5个, 点号. 三目运算?: 作用域访问符:: 运算符sizeof 以及.*
D.可以,例如重载对象的指向,典型有以后学到的智能指针
4、下列关于赋值运算符“=”重载的叙述中,正确的是( A)
A.赋值运算符只能作为类的成员函数重载
B.默认的赋值运算符实现了“深层复制”功能
C.重载的赋值运算符函数有两个本类对象作为形参
D.如果己经定义了复制拷贝构造函数,就不能重载赋值运算符
解析:
A. 赋值运算符在类中不显式实现时,编译器会生成一份默认的,此时用户在类外再将赋值运算符重载为全局的,就和编译器生成的默认赋值运算符冲突了,故赋值运算符只能重载成成员函数
B.默认的赋值运算符是按成员成员,属于浅赋值
C.参数只有一个,另一个通过this指针传递 D.两个函数的调用场景不同,相互没有影响
5、若要对data类中重载的加法运算符成员函数进行声明,下列选项中正确的是(A )
A.Data operator+(Data); B.Data operator(Data);
C.operator+(Data,Data); D.Data+(Data);
解析:
A.正确 B.语法错误,缺少运算符+
C.成员函数参数过多 D.没有运算符重载关键字operator
六、C++ | const成员函数
1、假设 AA 是一个类, AA* abc () const 是该类的一个成员函数的原型。若该函数返回 this 值,当用 x.abc ()调用该成员函数后, x 的值是(D )
A.可能被改变 B.已经被改变 C. 受到函数调用的影响 D.不变
解析:
A.此成员函数被定义为const常方法,代表在函数内部不能修改任何当前对象的数据成员,因此x不可能改变 B.错误,不能被改变 C.x的值在函数内部不受任何影响 D.正确
2、有一个类A,其数据成员如下: 则构造函数中,成员变量一定要通过初始化列表来初始化的是:(B )
class A
{
...
private:
int a;
public:
const int b;
float* &c;
static const char* d;
static double* e;
};
A.a b c B.b c C.b c d e D.b c d E.b F.c
解析:
A.a是不同数据成员,可以通过构造函数进行赋值
B.正确,常量以及引用只能通过初始化列表初始化
C.d,e是静态成员,只能在类外初始化
D.d是静态成员,只能在类外初始化
E.b常量只能通过初始化列表初始化,但不是最佳答案
F.c引用只能通过初始化列表初始化,但不是最佳答案
3、下面程序的运行结果是(D )
class A
{
public:
A(int a)
:_a1(a)
,_a2(_a1)
{}
void Print()
{
cout<<_a1<<" "<<_a2<<endl;
}
private:
int _a2;
int _a1;
}
int main()
{
A aa(1);
aa.Print();
}
A.输出1 1 B.程序崩溃 C.编译不通过 D.输出1 随机值
解析:
A.初始化顺序由定义类时的声明顺序决定,所以先初始化_a2,由于初始化_a2时_a1还未初始化,所以为随机值,故错误 B.程序正常运行 C.能编译通过 D.正确
4、在一个cpp文件里面,定义了一个static类型的全局变量,下面一个正确的描述是:( A)
A.只能在该cpp所在的编译模块中使用该变量
B.该变量的值是不可改变的
C.该变量不能在类的成员函数中引用
D.这种变量只能是基本类型(如int,char)不能是C++类型
解析:
A.正确,static限制了变量具有文件域
B.static变量是可以被改变的
C.可以被正常访问使用,以及通过成员来进行引用
D.静态变量也可以是自定义类型的变量
5、关于C++类中static 成员和对象成员的说法正确的是( C)
A.static 成员变量在对象构造时生成
B.static 成员函数在对象成员函数中无法调用
C.static 成员函数没有this指针
D.static 成员函数不能访问static 成员变量
解析:
A.static成员变量在对象生成之前生成
B.普通成员函数是可以调用static函数的
C.static函数属于所有对象共享,不具备this指针
D.static函数唯一能够访问的就是static变量或者其他static函数
6、下面程序段包含4个函数,其中具有隐含this指针的是( D)
int f1();
class T
{
public:static int f2();
private:friend int f3();
protect:int f4();
};
A.f1 B.f2 C.f3 D.f4
解析:
A.全局函数不具备this指针 B.static函数不具备this指针
C.友元函数不具备this指针 D.正确,普通成员方法具有隐藏的this指针
7、下面有关友元函数与成员函数的区别,描述错误的是( D)
A.友元函数不是类的成员函数,和普通全局函数的调用没有区别
B.友元函数和类的成员函数都可以访问类的私有成员变量或者是成员函数
C.类的成员函数是属于类的,调用的时候是通过指针this调用的
D.友元函数是有关键字friend修饰,调用的时候也是通过指针this调用的
解析:
A.友元函数不是类的成员函数,就相当于你的朋友再亲密也不是你的家人,既然不是类成员函数,那和普通成员函数调用一样,不需要通过对象调用
B.友元的目的就是为了访问类的私有数据,成员函数可以直接访问类的私有数据
C.类的成员函数属于类,调用时其内部数据会通过this指针来调用
D.友元函数不具备this指针,更谈不上通过this调用,故错误
8、一个类的友元函数能够访问类的(D )
A.私有成员 B.保护成员 C.公有成员 D.所有成员
解析:
A.可以访问,这也把一个函数声明为友元的目的 B.可以访问 C.可以访问
D.友元函数对一个类里面的所有成员,全部通吃,正确
9、求1+2+3+...+n_牛客题霸_牛客网
解析:
1. 题目要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句A?B:C
说明不能采用常规方法进行累加求和
2. 充分利用C++特性,构造对象构造函数会自动调用的特点(调用n次),让求和在构造函数中进行完成
3. 由于所有对象要针对相同的和进行更新,所以其成员定义为static(设置为静态)
class Solution
{
public:
class Sum
{
public:
Sum()
{
_sum += _i;
_i++;
}
};
int Sum_Solution(int n)
{
_i = 1;
_sum = 0;
Sum array[n];
return _sum;
}
static size_t _sum;
static size_t _i;
};
size_t Solution::_sum = 0;
size_t Solution::_i = 1;
10、计算日期到天数转换_牛客题霸_牛客网
解析: 通过枚举每个月的1号是这一年的第几天,从而进行累加求和即可,其中注意闰年的处理
#include<iostream>
using namespace std;
int main()
{
int year, month, day;
while(cin>>year>>month>>day)
{
int monthDays[13] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
int nday = monthDays[month-1] + day;
if(month > 2 &&((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))
{
nday += 1;
}
cout<<nday<<endl;
}
return 0;
}
11、日期差值_牛客题霸_牛客网
解析:
1. 分别求出每一个日期与0000年0月1日距离的天数
2. 两个距离天数相减即可得到两个日期相差的天数
其中,y:year,闰年分为普通闰年(能被4整除但不能被100整除)跟世纪闰年(能被400整除),365*year好理解,就是先算平年的所有天,y/4-y/100是计算0001-xxxx年间有多少个普通闰年,
y/400是计算有多少个世纪闰年(多少个闰年就多多少天)
#include <iostream>
using namespace std;
//平年从1月到n月的天数
int mon[12]={0,31,59,90,120,151,181,212,243,273,304,334};
//给出年月日,计算距离0000年0月1日的天数和
int CountDay(int y,int m,int d)
{
// 计算0-y年的天数
int yearDay = y*365+y/4-y/100+y/400;
// 计算到0-m月的天数
int monthDay = mon[m-1];
if(m > 2 && ((y%4 == 0 && y%100 != 0) || y%400==0))
monthDay += 1;
return yearDay + monthDay + d;
}
int main()
{
int year1,month1,day1;
scanf("%4d%2d%2d",&year1,&month1,&day1);
int n1 = CountDay(year1,month1,day1);
int year2,month2,day2;
scanf("%4d%2d%2d",&year2,&month2,&day2);
int n2 = CountDay(year2,month2,day2);
cout<<abs(n1-n2)+1<<endl;//返回一个绝对值
}
七、C++ | 类相关OJ题
1、日期累加_牛客题霸_牛客网
解析:
-
读取输入:首先读取样例个数 n,然后对每个样例读取初始日期(年、月、日)和需要累加的天数。
-
初始化月份天数:定义一个数组
days
,存储每个月的默认天数,并根据是否为闰年动态调整2月的天数。 -
累加天数并处理进位:将累加的天数加到当前日期上,如果当前日期超过当月天数,则进入下一个月,并更新日期。若月份超过12,则进入下一年。
-
输出结果:最终按照
yyyy-mm-dd
的格式输出计算后的日期。
#include<iostream>
using namespace std;
int main()
{
int n;
while (cin >> n)
{
for (int i = 0; i < n; i++)
{
int y, m, d, num;
int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
cin >> y >> m >> d >> num;
d += num;
while (d > days[m - 1])
{
if (y % 400 == 0 || (y % 4 == 0 && y % 100 != 0))
days[1] = 29;
else
days[1] = 28;
d -= days[m - 1];
if(d == 0)
d = 1;
m++;
if (m == 13)
{
y++;
m = 1;
}
}
printf("%4d-%02d-%02d\n", y, m, d);
}
}
return 0;
}
2、打印日期_牛客题霸_牛客网
解析:
-
初始化月份天数:定义一个数组
get_monthsday
,存储每个月的默认天数,并根据是否为闰年动态调整2月的天数。 -
读取输入:从输入中读取年份和一年中的第 n 天。
-
遍历月份:从1月开始,逐月累加天数,直到累加的天数小于当前月份的天数,从而确定目标日期所在的月份和日期。
-
输出结果:按照
yyyy-mm-dd
的格式输出目标日期,注意月份需要加1(因为数组索引从0开始)。
#include <iostream>
using namespace std;
int main()
{
int get_monthsday[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int year, num;
while (cin >> year >> num)
{
// 判断是否为闰年
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
{
get_monthsday[1] = 29; // 闰年2月为29天
}
else
{
get_monthsday[1] = 28; // 平年2月为28天
}
int month = 0;
int day = num;
// 遍历每个月,直到找到对应的月份
while (day > get_monthsday[month])
{
day -= get_monthsday[month];
month++;
}
// 输出结果
printf("%04d-%02d-%02d\n", year, month + 1, day); // 注意月份需要+1,因为数组是从0开始的
}
return 0;
}
4、变量所在哪个内存区域以及变量所占空间大小是多少?
int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
static int staticVar = 1;
int localVar = 1;
int num1[10] = {1, 2, 3, 4};
char char2[] = "abcd";
char* pChar3 = "abcd";
int* ptr1 = (int*)malloc(sizeof (int)*4);
int* ptr2 = (int*)calloc(4, sizeof(int));
int* ptr3 = (int*)realloc(ptr2, sizeof(int)*4);
free (ptr1);
free (ptr3);
}
1. 选择题:
选项: A.栈 B.堆 C.数据段(静态区) D.代码段(常量区)
globalVar在哪里?__C__ staticGlobalVar在哪里?__C__
staticVar在哪里?__C__ localVar在哪里?__A__
num1 在哪里?__A__
分析:
globalVar全局变量在数据段 staticGlobalVar静态全局变量在静态区
staticVar静态局部变量在静态区 localVar局部变量在栈区
num1局部变量在栈区
char2在哪里?__A__ *char2在哪里?__A__
pChar3在哪里?__A__ *pChar3在哪里?__D__
ptr1在哪里?__A__ *ptr1在哪里?__B__
分析:
char2局部变量在栈区
char2是一个数组,把后面常量串拷贝过来到数组中,数组在栈上,所以*char2在栈上
pChar3局部变量在栈区 *pChar3得到的是字符串常量字符在代码段
ptr1局部变量在栈区 *ptr1得到的是动态申请空间的数据在堆区
2. 填空题:
sizeof(num1) = __40__;//数组大小,10个整形数据一共40字节
sizeof(char2) = __5__;//包括\0的空间
strlen(char2) = __4__;//不包括\0的长度
sizeof(pChar3) = __4__;//pChar3为指针
strlen(pChar3) = __4__;//字符串“abcd”的长度,不包括\0的长度
sizeof(ptr1) = __4__;//ptr1是指针
5、下面有关c++内存分配堆栈说法错误的是(D )
A.对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制
B. 对于栈来讲,生长方向是向下的,也就是向着内存地址减小的方向;对于堆来讲,它的生长方向是向上的,是向着内存地址增加的方向增长
C.对于堆来讲,频繁的 new/delete 势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题
D.一般来讲在 32 位系统下,堆内存可以达到4G的空间,但是对于栈来讲,一般都是有一定的空间大小的
解析:
A.栈区主要存在局部变量和函数参数,其空间的管理由编译器自动完成,无需手动控制,堆区是自己申请的空间,在不需 要时需要手动释放
B.栈区先定义的变量放到栈底,地址高,后定义的变量放到栈顶,地址低,因此是向下生长的,堆区则相反
C.频繁的申请空间和释放空间,容易造成内存碎片,甚至内存泄漏,栈区由于是自动管理,不存在此问题
D.32位系统下,最大的访问内存空间为4G,所以不可能把所有的内存空间当做堆内存使用,故错误
6、C++中关于堆和栈的说法,哪个是错误的:( C)
A.堆的大小仅受操作系统的限制,栈的大小一般较小
B.在堆上频繁的调用new/delete容易产生内存碎片,栈没有这个问题
C.堆和栈都可以静态分配
D.堆和栈都可以动态分配
解析:
A.堆大小受限于操作系统,而栈空间一般有系统直接分配
B.频繁的申请空间和释放空间,容易造成内存碎片,甚至内存泄漏,栈区由于是自动管理,不存在此问题
C.堆无法静态分配,只能动态分配
D.栈可以通过函数_alloca进行动态分配,不过注意,所分配空间不能通过free或delete进行释放
7、c++语言中,类ClassA的构造函数和析构函数的执行次数分别为(D )
ClassA *pclassa=new ClassA[5];
delete pclassa;
A.5,1 B.1,1 C.5,5 D.程序可能崩溃
解析:
A.申请对象数组,会调用构造函数5次,delete由于没有使用[],此时只会调用一次析构函数,但往往会引发程序崩溃 B.构造函数会调用5次
C.析构函数此时只会调用1次,要想完整释放数组空间,需要使用[] D.正确
8、函数参数使用的空间是在()中申请的,malloc或new是在()中申请空间的?(B)
A.堆,栈 B.栈,堆 C.栈, 栈 D.堆,堆
解析:
A.参数在栈空间存放,malloc或new申请的空间为堆区 B.正确
C.参数在栈空间存放,malloc或new申请的空间为堆区
D.参数在栈空间存放,malloc或new申请的空间为堆区
9、下面有关malloc和new,说法错误的是? ( C)
A.new 是创建一个对象(先分配空间,再调构造函数初始化), malloc分配的是一块内存
B.new 初始化对象,调用对象的构造函数,对应的delete调用相应的析构函数,malloc仅仅分配内存,free仅仅回收内存
C.new和malloc都是保留字,不需要头文件支持
D.new和malloc都可用于申请动态内存,new是一个操作符,malloc是是一个函数
解析:
A.new会申请空间,同时调用构造函数初始化对象,malloc只做一件事就是申请空间
B.new/delete与malloc/free最大区别就在于是否会调用构造函数与析构函数
C.需要头文件malloc.h,只是平时这个头文件已经被其他头文件所包含了,用的时候很少单独引入,故错误
D.new是操作符,malloc是函数
10、设已经有A,B,C,D4个类的定义,程序中A,B,C,D析构函数调用顺序为? ( B)
C c;
void main()
{
A*pa=new A();
B b;
static D d;
delete pa;
}
A.A B C D B.A B D C C.A C D B D.A C B D
解析:
首先手动释放pa, 所以会先调用A的析构函数,其次会跟定义相反的顺序释放局部对象,这里只有b,就释放b,再释放静态局部对象d,再释放全局对象c
11、使用 char* p = new char[100]申请一段内存,然后使用delete p释放,有什么问题?( B)
A.会有内存泄露 B.不会有内存泄露,但不建议用
C.编译就会报错,必须使用delete []p D.编译没问题,运行会直接崩溃
解析:
A.对于内置类型,此时delete就相当于free,因此不会造成内存泄漏 B.正确
C.编译不会报错,建议针对数组释放使用delete[],如果是自定义类型,不使用方括号就会运行时错误 D.对于内置类型,程序不会崩溃,但不建议这样使用
12、以下代码中,A 的构造函数和析构函数分别执行了几次: ( B)
A*pa=new A[10];
delete []pa;
A.1、1 B.10、10 C.1、10 D.10、1
解析:
A.申请数组空间,构造函数调用的次数就是数组的大小 B.正确
C.申请数组空间,构造函数调用的次数就是数组的大小
D.如果释放数组空间,delete使用了[],则会对应的调用数组大小次数的析构函数