类与对象 内存管理习题
一、填空题
(1)类定义中关键字private、public和protected以后的成员的访问权限分别是 私有、公有和保护。如果没有使用关键字,则所有成员默认定义为private权限。具有public访问权限的数据成员才能被不属于该类的函数所直接访问。
(2)定义成员函数时,运算符“::”是 作用域 运算符,“MyClass::”用于表明其后的成员函数是在“MyClass类”中说明的。
(3)在程序运行时,通过为对象分配内存来创建对象。在创建对象时,使用类作为样板,故称对象为类的实例。
(4)假定Dc是一个类,则执行“Dc a[10],b(2)”语句时,系统自动调用该类构造函数的次数为11 。
(5)对于任意一个类,析构函数的个数最多为 1 个。
(6)delete运算符通常用于实现释放该类对象中指针成员所指向的动态存储空间的任务。
(7)C++程序的内存格局通常分为4个区: 数据区、代码区、栈区和堆区。
(8)数据定义为全局变量,破坏了数据的封装性;较好的解决办法是将所要共享的数据定义为类的静态成员。
(9)静态数据成员和静态成员函数可由任意访问权限许可函数访问。
(10)友元函数和友元类统称为友元。
(11)友元的正确使用能提高程序的效率,但破坏了类的封装性和数据的隐蔽性。
(12)若需要把一个类A定义为一个类B的友元类,则应在类B的定义中加入一条语句:friend class A 。
二、选择题(至少选一个,可以多选)
(1)以下不属于类存取权限的是(B)。
A.public B.static C.protected D.private
(2)有关类的说法不正确的是(BC)。
A.类是一种用户自定义的数据类型
B.只有类的成员函数才能访问类的私有数据成员
C.在类中,如不做权限说明,所有的数据成员都是公有的
D.在类中,如不做权限说明,所有的数据成员都是私有的
(3)在类定义的外部,可以被任意函数访问的成员有(C)。
A.所有类成员 B.private或protected的类成员 C.public的类成员 D.public或private的类成员
(4)关于类和对象的说法(C)是错误的。
A.对象是类的一个实例
B.任何一个对象只能属于一个具体的类
C.一个类只能有一个对象
D.类与对象的关系和数据类型与变量的关系相似
(5)设MClass是一个类,dd是它的一个对象,pp是指向dd的指针,cc是dd的引用,则对成员的访问,对象dd可以通过(B)进行,指针pp可以通过(D)进行,引用cc可以通过(B)进行。
A. :: B. . C.& D. —>
(6)关于成员函数的说法中不正确的是(C)。
A.成员函数可以无返回值
B.成员函数可以重载
C.成员函数一定是内联函数
D.成员函数可以设定参数的默认值
(7)下面对构造函数的不正确描述是(B)。
A.系统可以提供默认的构造函数
B.构造函数可以有参数,所以也可以有返回值
C.构造函数可以重载
D.构造函数可以设置默认参数
(8)假定A是一个类,那么执行语句“A a,b(3),*p;”调用了(B)次构造函数。
A.1 B.2 C.3 D.4
(9)下面对茨沟函数的正确描述是(AC)。
A.系统可以提供默认的析构函数
B.析构函数必须由用户定义
C.析构函数没有参数
D.析构函数可以设置默认参数
(10)类的析构函数是(D)时被调用的。
A.类创建 B.创建对象 C.引用对象 D.释放对象
(11)创建一个类的对象时,系统自动调用(B);撤销对象时,系统自动调用(C)。
A.成员函数 B.构造函数 C.析构函数 D.拷贝构造函数
(12)通常拷贝构造函数的参数是(C)。
A.某个对象名 B.某个对象的成员名 C.某个对象的引用名 D.某个对象的指针名
(13)关于this指针的说法正确的是(B)。
A.this指针必须显式说明
B.当创建一个对象后,this指针就指向该对象
C.成员函数拥有this指针
D.静态成员函数拥有this指针
(14)下列关于子对象的描述中,(B)是错误的。
A.子对象是类的一种数据成员,它是另一个类的对象
B.子对象可以是自身类的对象
C.对子对象的初始化要包含在该类的构造函数中
D.一个类中能含有多个子对象作其成员
(15)对new运算符的下列描述中,(B)是错误的。
A.它可以动态创建对象和对象数组
B.用它创建对象数组时必须指定初始值
C.用它创建对象时要调用构造函数
D.用它创建的对象数组可以使用运算符delete来一次释放
(16)对delete运算符的下列描述中,(D)是错误的。
A.用它可以释放用new运算符创建的对象和对象数组
B.用它释放一个对象时,它作用于一个new所返回的指针
C.用它释放一个对象数组式,它作用的指针名前须加下标运算符【】
D.用它可以一次释放用new运算符创建的多个对象
(17)关于静态数据成员,下面叙述不正确的是(C)。
A.使用静态数据成员,实际上是为了消除全局变量
B.可以使用“对象名.静态成员”或者“类名::静态成员”来访问静态数据成员
C.静态数据成员只能在静态成员函数中引用
D.所有对象的静态数据成员占用同一内存单元
(18)对静态数据成员的不正确描述是(CD)。
A.静态成员不属于对象,是类的共享成员
B.静态数据成员要在类外定义和初始化
C.调用静态成员函数是要通过类或对象激活,所以静态成员函数拥有this指针
D.只有静态成员函数可以操作静态数据成员
(19)下面的选项中,静态成员函数不能直接访问的是(D)。
A.静态数据成员 B.静态成员函数 C.类以外的函数和数据 D.非静态数据成员
(20)在类的定义中,引入友元的原因是(A)。
A.提高效率 B.深化使用类的封装性 C.提高程序的可读性 D.提高数据的隐蔽性
(21)友元类的声明方法是(A)。
A.friend class<类名> B.youyuan class<类名> C.class friend<类名> D.friends class<类名>
(22)下面对友元的错误描述是(D)。
A.关键字friend用于声明友元
B.一个类中的成员函数可以是另一个类色友元
C.友元函数访问对象的成员不受访问特性影响
D.友元函数通过this指针访问对象成员
(23)下面选项中,(C)不是类的成员函数。
A.构造函数 B.析构函数 C.友元函数 D.拷贝构造函数
三、简答题
(1)类与对象有什么关系?
答:类是一种用户自己定义的数据类型,和其他数据类型不同的是,组成这种类型的不仅可以有数据,而且可以有对数据进行操作的函数。程序员可以使用这个新类型在程序中声明新的变量,具有类类型的变量称为对象。创建对象时,类被用做样板,对象称为类的实例。
(2)类定义的一般形式是什么?其成员有哪几种访问权限?
答:定义类一般形式为:
class 类名{
public:
<公有数据和函数>
protected:
<保护数据和函数>
private:
<私有数据和函数>
};
访问权限共有3种:分别是公有(public)、保护(protected)和私有(private)。
(3)类的实例化是指创建类的对象还是定义类?
答:是指创建类的对象。
(4)什么是this指针?它的主要作用是什么?
答:this指针是C++语言为成员函数提供的一个隐含对象指针,它不能被显式声明。this指针是一个局部量,局部于某个对象。不同的对象调用同一个成员函数时,编译器根据this指针来确定应该引用哪一个对象的数据成员。
(5)什么叫做拷贝构造函数?拷贝构造函数何时被调用?
答:拷贝构造函数是一种特殊的构造函数,它的作用是用一个已经存在的对象去初始化另一个对象。为了保证所引用的对象不被修改,通常把引用参数声明为const参数。在以下3种情况下,拷贝构造函数都会被自动调用:
当用类的一个对象去初始化该类的另一个对象时;当函数的形参是类的对象,进行形参和实参结合时;当函数的返回值是类的对象,函数执行完成返回调用者时。
四、程序分析题(写出程序的输出结果,并分析结果)
(1)
AI生成项目
cpp
运行
#include<iostream>
using namespace std;
class Test
{
private:
int num;
public:
Test();
Test(int n);
};
Test::Test()
{
cout<<"Init defa"<<endl;
num=0;
}
Test::Test(int n)
{
cout<<"Init"<<""<<n<<endl;
num=n;
}
int main()
{
Test x[2];
Test y(15);
return 0;
}
输出结果:

结果分析:程序声明了2个对象x和y,类中有2个构造函数。程序先执行语句1,创建对象x,调用默认构造函数。由于对象x是对象数组,每个数组元素被创建时都要调用构造函数,所有默认构造函数被调用了2次,输出第1、2行结果。程序接着执行语句2,创建对象y,调用带一个参数的构造函数,输出第3行结果。
(2)
AI生成项目
cpp
运行
#include<iostream>
using namespace std;
class Xx
{
private:
int num;
public:
Xx(int x){num=x;}
~Xx(){cout<<"dst"<<num<<endl;}
};
int main()
{
Xx w(5);
cout<<"Exit main"<<endl;
return 0;
}
输出结果:

结果分析:程序声明了一个对象w。先执行语句1,创建对象w,调用构造函数,num得到初值5 。接着执行语句2,输出第一行结果,当程序结束时,释放对象w,析构函数被调用,输出第2行结果。
(3)将例3.10中的Whole类如下修改,其他部分不变,写出输出结果。
#include<iostream>
using namespace std;
class Part
{
public:
Part();
Part(int x);
~Part();
private:
int val;
};
Part::Part()
{
val=0;
cout<<"Default constructor of Part"<<endl;
}
Part::Part(int x)
{
val=x;
cout<<"Constructor of Part"<<","<<val<<endl;
}
Part::~Part()
{
cout<<"Destructor of Part"<<endl;
}
class Whole
{
public:
Whole(int i);
Whole(){};
~Whole();
private:
Part p1;
Part p2;
Part p3;
};
Whole::Whole(int i):p2(i),p1()
{
cout<<"Constructor of Whole"<<endl;
}
Whole::~Whole()
{
cout<<"Destructor of Whole"<<endl;
}
int main()
{
Whole w(3);
return 0;
}
输出结果:

结果分析:程序的Whole类中出现了类Part的3个对象p1、p2和p3,作为该类的数据成员,则p1、p2和p3被称为子对象。当建立Whole类的对象w时,子对象p1、p2和p3被建立,相应的构造函数被执行。由于p1在Whole类中先说明,所以先执行它所使用的构造函数,即类Part的默认构造函数,接着p2执行它所使用的有参构造函数,紧接着初始化p3,由于Whole类构造函数的成员初始化列表中没有子对象p3进行初始化的选项,所以执行类Part的默认构造函数,当所有子对象被构造完之后,对象w的构造函数才被执行,从而得到前4行输出结果,而后4行是执行相应析构函数的输出结果。
(4)
AI生成项目
cpp
运行
#include<iostream>
using namespace std;
class Book
{
public:
Book(int w);
static int sumnum;
private:
int num;
};
Book::Book(int w)
{
num=w;
sumnum-=w;
}
int Book::sumnum=120;
int main()
{
Book b1(20);
Book b2(70);
cout<<Book::sumnum<<endl;
return 0;
}
输出结果:30
结果分析:程序中语句1对静态成员sumnum进行初始化,sumnum得到初始值120,执行语句2时调用构造函数,sumnum变为100.接着语句3,再调用构造函数,sumnum变为30.
五、程序设计题
(1)声明一个Circle类,有数据成员radius(半径),成员函数area(),计算圆的面积,构造一个Circle的对象进行测试。
AI生成项目
cpp
运行
#include <iostream>
using namespace std;
class Circle
{
public:
float GetArea();
Circle(); //重载构造函数
Circle(float r);//重载构造函数
public:
float Radius;
};
Circle::Circle()
{
Radius=1.0;
}
Circle::Circle(float r)
{
Radius=r;
}
float Circle::GetArea()
{
return Radius*Radius*3.14;
}
int main()
{
Circle c1;
cout<<"圆1的面积:"<<c1.GetArea()<<endl;
Circle c2(10);
cout<<"圆2的面积:"<<c2.GetArea()<<endl;
return 0;
}
输出结果:

2)重新编写程序分析题(4)的程序,设计一个静态成员函数,用来输出程序分析题(4)中静态数据成员的值。
原链接:https://blog.csdn.net/JYF1182813178/article/details/80844196
习题1:(const成员函数)
假设 AA 是一个类, AA* abc () const 是该类的一个成员函数的原型。若该函数返回 this 值,当用 x.abc ()调用该成员函数后, x 的值是( )
A.可能被改变
B.已经被改变
C. 受到函数调用的影响
D.不变
A.此成员函数被定义为const常方法,代表在函数内部不能修改任何当前对象的数据成员,因此x不可能改变
B.错误,不能被改变
C.x的值在函数内部不受任何影响
D.正确
习题2:(初始化列表)
有一个类A,其数据成员如下: 则构造函数中,成员变量一定要通过初始化列表来初始化的是:( )
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:(类型转换)
下面程序的运行结果是( )?
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:(static)
在一个cpp文件里面,定义了一个static类型的全局变量,下面一个正确的描述是:( )
A.只能在该cpp所在的编译模块中使用该变量
B.该变量的值是不可改变的
C.该变量不能在类的成员函数中引用
D.这种变量只能是基本类型(如int,char)不能是C++类型
A.正确,static限制了变量具有文件域
B.static变量是可以被改变的
C.可以被正常访问使用,以及通过成员来进行引用
D.静态变量也可以是自定义类型的变量
习题5:(static成员和对象成员)
关于C++类中static 成员和对象成员的说法正确的是( )
A.static 成员变量在对象构造时生成
B.static 成员函数在对象成员函数中无法调用
C.static 成员函数没有this指针
D.static 成员函数不能访问static 成员变量
A.static成员变量在对象生成之前生成
B.普通成员函数是可以调用static函数的
C.static函数属于所有对象共享,不具备this指针
D.static函数唯一能够访问的就是static变量或者其他static函数
习题6:(友元函数)
下面程序段包含4个函数,其中具有隐含this指针的是( )
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指针
A.static成员变量在对象生成之前生成
B.普通成员函数是可以调用static函数的
C.static函数属于所有对象共享,不具备this指针
D.static函数唯一能够访问的就是static变量或者其他static函数
习题7:(友元函数)
下面有关友元函数与成员函数的区别,描述错误的是?( )
A.友元函数不是类的成员函数,和普通全局函数的调用没有区别
B.友元函数和类的成员函数都可以访问类的私有成员变量或者是成员函数
C.类的成员函数是属于类的,调用的时候是通过指针this调用的
D.友元函数是有关键字friend修饰,调用的时候也是通过指针this调用的
A.友元函数不是类的成员函数,就相当于你的朋友再亲密也不是你的家人,既然不是类成员函数,那和普通成员函数调用一样,不需要通过对象调用
B.友元的目的就是为了访问类的私有数据,成员函数可以直接访问类的私有数据
C.类的成员函数属于类,调用时其内部数据会通过this指针来调用
D.友元函数不具备this指针,更谈不上通过this调用,故错误
习题8:(友元函数)
一个类的友元函数能够访问类的( )
A.私有成员
B.保护成员
C.公有成员
D.所有成员
A.可以访问,这也是把一个函数声明为友元的目的
B.可以访问
C.可以访问
D.友元函数对一个类里面的所有成员,全部通吃,正确
C/C++内存管理
习题1:
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);
}
选择题:
选项: A.栈 B.堆 C.数据段(静态区) D.代码段(常量区)
globalVar在哪里?____ staticGlobalVar在哪里?____
staticVar在哪里?____ localVar在哪里?____
num1 在哪里?____
char2在哪里?____ *char2在哪里?___
pChar3在哪里?____ *pChar3在哪里?____
ptr1在哪里?____ *ptr1在哪里?____
填空题:
sizeof(num1) = ____;
sizeof(char2) = ____; strlen(char2) = ____;
sizeof(pChar3) = ____; strlen(pChar3) = ____;
sizeof(ptr1) = ____;
选择题:
选项: 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得到的是动态申请空间的数据在堆区
填空题:
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是指针
习题2:(c++内存分配堆栈)
下面有关c++内存分配堆栈说法错误的是( )
A.对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制
B. 对于栈来讲,生长方向是向下的,也就是向着内存地址减小的方向;对于堆来讲,它的生长方向是向上的,是向着内存地址增加的方向增长
C.对于堆来讲,频繁的 new/delete 势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题
D.一般来讲在 32 位系统下,堆内存可以达到4G的空间,但是对于栈来讲,一般都是有一定的空间大小的
A.栈区主要存在局部变量和函数参数,其空间的管理由编译器自动完成,无需手动控制,堆区是自己申请的空间,在不需 要时需要手动释放
B.栈区先定义的变量放到栈底,地址高,后定义的变量放到栈顶,地址低,因此是向下生长的,堆区则相反
C.频繁的申请空间和释放空间,容易造成内存碎片,甚至内存泄漏,栈区由于是自动管理,不存在此问题
D.32位系统下,最大的访问内存空间为4G,所以不可能把所有的内存空间当做堆内存使用,故错误
习题3:(堆和栈)
C++中关于堆和栈的说法,哪个是错误的:( )
A.堆的大小仅受操作系统的限制,栈的大小一般较小
B.在堆上频繁的调用new/delete容易产生内存碎片,栈没有这个问题
C.堆和栈都可以静态分配
D.堆和栈都可以动态分配
A.堆大小受限于操作系统,而栈空间一般有系统直接分配
B.频繁的申请空间和释放空间,容易造成内存碎片,甚至内存泄漏,栈区由于是自动管理,不存在此问题
C.堆无法静态分配,只能动态分配
D.栈可以通过函数_alloca进行动态分配,不过注意,所分配空间不能通过free或delete进行释放
习题4:(自定义类型的内存管理)
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.正确
习题5:(堆和栈)
函数参数使用的空间是在()中申请的,malloc或new是在()中申请空间的?()
A.堆,栈
B.栈,堆
C.栈, 栈
D.堆,堆
A.参数在栈空间存放,malloc或new申请的空间为堆区
B.正确
C.参数在栈空间存放,malloc或new申请的空间为堆区
D.参数在栈空间存放,malloc或new申请的空间为堆区
习题6:(malloc和new的区别)
下面有关malloc和new,说法错误的是? ( )
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是函数
习题7:(new)
设已经有A,B,C,D4个类的定义,程序中A,B,C,D析构函数调用顺序为? ( )
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
习题8:(内置类型的内存管理)
使用 char* p = new char[100]申请一段内存,然后使用delete p释放,有什么问题?( )
A.会有内存泄露
B.不会有内存泄露,但不建议用
C.编译就会报错,必须使用delete []p
D.编译没问题,运行会直接崩溃
A.对于内置类型,此时delete就相当于free,因此不会造成内存泄漏
B.正确
C.编译不会报错,建议针对数组释放使用delete[],如果是自定义类型,不使用方括号就会运行时错误
D.对于内置类型,程序不会崩溃,但不建议这样使用
习题9:(new和delete的次数问题)
以下代码中,A 的构造函数和析构函数分别执行了几次: ( )
A*pa=new A[10];
delete []pa;
A.1、1
B.10、10
C.1、10
D.10、1
A.申请数组空间,构造函数调用的次数就是数组的大小
B.正确
C.申请数组空间,构造函数调用的次数就是数组的大小
D.如果释放数组空间,delete使用了[],则会对应的调用数组大小次数的析构函数
编程题
求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)
代码如下:
class Sum
{
public:
Sum()
{
_ret += _i;
++_i;
}
static int GetRet()
{
return _ret;
}
private:
static int _i;
static int _ret;
};
int Sum::_i = 1;
int Sum::_ret = 0;
class Solution {
public:
int Sum_Solution(int n) {
// 变⻓数组
Sum arr[n];
return Sum::GetRet();
}
};
原文链接:https://blog.csdn.net/Mr_Xuhhh/article/details/142288324

浙公网安备 33010602011771号