第六章问题对象的指针、this指针、const、new和delete.
- 格式:doc
- 大小:29.00 KB
- 文档页数:15
new 和 delete首先,你需要知道程序在内存中。
它分为四部分:code:代码data: 数据(全局、静态变量)stack:栈(局部变量)heap:堆(你负责的地方,比如用来动态内存分配,即new和delete)程序运行时所需要的数据空间,通常是在程序设计时通过定义变量或数组的方式,由系统预先分配。
比如定义一个对象,在程序运行过程,它的空间不能随时释放。
【产生背景】:①在程序设计时,有些数据空间的大小和多少在编写程序时还不能确定,只有在程序运行时才能确定。
②有时希望在需要对象时才建立,不需要就立刻撤销它,释放其内存供别的数据使用。
【解决】:使用堆(heap)内存可以实现这一功能。
堆是一种内存空间,它允许程序运行时根据需要申请大小的内存空间。
堆又称动态内存分配。
【使用方法】:new运算符:1、使用格式:指针=new 数据类型名;指针=new 数据类型名(初始值);作用: 从内存的动态区域申请指定数据类型所需的存储单元。
若分配成功,该存储单元的首地址赋给指针,否则,指针得到一个空地址。
例如:(1) double *p;p=new double;(2) double *p;p=new double(12.3576); //分配同时初始化2、指针=new 数据类型〔元素个数〕用new在堆中申请一块连续的存储空间(一维数组)例:int size, *ip;cin>>size;ip=new int[size]; //创建size个元素的整型数组char *sp=new char[20]; //创建20个字符的字符数组delete运算符:使用格式:delete 指针名; //释放指针所指内存单元delete 〔〕指针名; //释放数组内存单元作用:释放用new创建的动态存储单元。
例如:int *pi=new int(5); //创建delete pi; //释放pi=new int; //再创建【注意】:delete运算符并不删除指针。
this指针及用法this指针是C++中的一个特殊指针,它指向当前对象的地址。
它主要用于在类的成员函数中访问当前对象的成员变量和成员函数。
使用this指针有以下几个方面的用法:1. 访问成员变量:在类的成员函数中,可以使用this指针来访问当前对象的成员变量。
这是因为成员函数中的变量名可能与成员变量名相同,使用this指针可以明确指出要访问的是成员变量而不是局部变量。
例如:cpp.class MyClass {。
public:void setX(int x) {。
this->x = x; // 使用this指针访问成员变量x.}。
private:int x;};2. 返回当前对象:在类的成员函数中,可以使用this指针返回当前对象的引用。
这可以方便地实现链式调用。
例如:cpp.class MyClass {。
public:MyClass& setX(int x) {。
this->x = x;return this; // 返回当前对象的引用。
}。
private:int x;};3. 在构造函数中使用:在构造函数中,this指针指向正在创建的对象。
这可以用于在构造函数中进行成员变量的初始化。
例如: cpp.class MyClass {。
public:MyClass(int x) {。
this->x = x; // 使用this指针初始化成员变量x.}。
private:int x;};4. 解决命名冲突:当类的成员变量与函数参数或局部变量同名时,可以使用this指针来区分它们。
例如:cpp.class MyClass {。
public:void setData(int data) {。
this->data = data; // 使用this指针访问成员变量data.}。
private:int data;};总结起来,this指针在C++中用于在类的成员函数中访问当前对象的成员变量和成员函数,解决命名冲突以及返回当前对象的引用。
c++this的用法在C++中,this是一个特殊的指针,它指向当前对象的地址。
this常常在类方法中使用,用于在类方法中访问对象的成员变量和成员函数。
一、this的基本用法在类方法中,this指针指向调用该方法的对象。
通过使用this指针,可以在类方法中直接访问对象的成员变量和成员函数,而无需使用对象名。
例如:```cppclassMyClass{intx;public:voidsetX(intvalue){x=value;//直接访问成员变量,无需使用对象名}voidprintX(){cout<<x;//直接访问成员变量,无需使用对象名,也可以使用this->x}};```在上面的例子中,setX()和printX()都是类方法,它们都使用了this指针来访问对象的成员变量x。
二、this的注意事项1.避免重复使用对象名和this指针:在类方法中,尽量避免重复使用对象名和this指针来访问对象的成员变量和成员函数。
这会导致代码冗余和难以阅读。
2.使用this指针时需要小心指针赋值:如果一个类方法被另一个类方法返回,并且该方法返回一个指向当前对象的指针,那么这个指针需要使用对象的地址来赋值。
否则,会导致悬空指针或未定义的行为。
3.this指针是类的内部指针:this指针是类的内部指针,不应该被外部代码直接访问。
如果外部代码需要访问对象的成员变量和成员函数,应该使用对象名来访问。
4.this指针的传递:如果需要在类方法中使用其他类的方法,可以将this 指针作为参数传递给其他类的方法。
但是需要注意,传递this指针可能会导致代码难以理解和维护。
三、this的常见用法示例下面是一些使用this指针的常见用法示例:1.在构造函数中使用this指针:在构造函数中,可以使用this指针来访问对象的成员变量和成员函数。
例如:```cppclassMyClass{intx;public:MyClass(intvalue):x(value){}//使用this指针初始化成员变量x};```2.在析构函数中使用this指针:在析构函数中,可以使用this指针来释放对象的资源。
1.C++的流库预定义了4个流,它们是cin、cout、clog和__cerr_。
2. 每个对象都是所属类的一个_ 实例3. 在已经定义了整型指针ip后,为了得到一个包括10个整数的数组并由ip所指向,应使用语句int *ip=new int[10];4. 函数模板中紧随template之后尖括号内的类型参数都要冠以保留字__class_。
5. 表达式cout<<end1 还可表示为__’\n’_。
6. 在C++中,访问一个指针所指向的对象的成员所用的指向运算符是->。
7. 假如一个类的名称为MyClass,使用这个类的一个对象初始化该类的另一个对象时,可以调用复制或拷贝构造函数来完成此功能。
8. 对赋值运算符进行重载时,应声明为类成员函数。
9. 如果要把A类成员函数f()且返回值为void声明为类B的友元函数,则应在类B的定义中加入的语句___。
答案:friend void A::f();[解析]成员函数作为另一个类的友元函数,格式为:friend 返回类型类名::函数(形参)。
10. 控制格式输入输出的操作中,函数___是用来设置填充字符。
要求给出函数名和参数类型答案:setfill(char)[解析]格式控制方法的使用,如setw,setfill等等。
11. C++语言支持的两种多态性分别是编译时的多态性和___的多态性。
答案:运行时[解析]多态性包括静态的(编译时)多态性和动态的(运行时)多态性。
12.13. 定义类动态对象数组时,元素只能靠自动调用该类的___来进行初始化。
答案:无参构造函数[解析]使用new 创建动态对象数组,不能有参数,所以只能调用无参的构造函数,初始化对象 15. 一个抽象类的派生类可以实例化的必要条件是实现了所有的___。
答案:纯虚函数的定义[解析]抽象类只因有纯虚函数,所以不能被实例化,所以派生类要实例化必须对纯虚函数进行定义。
17. 在用C++进行程序设计时,最好用___代替malloc。
new和delete的用法
new和delete用法
1、new和delete是C++中标准库规定的关键字之一,即动态内存分配
管理的操作符。
2、new用于在运行时分配内存空间并返回对象的首地址指针,delete
用于释放指定对象占用的内存空间。
3、new语法格式:指针变量= new 数据类型;
4、delete语法格式:delete 指针变量;
5、new和delete结合使用时,应当注意遵守C++定义的动态内存的匹
配原则,即要严格地按照一对new语句和一对delete语句的比例来使用。
6、new运算符可以在括号中指定空间大小,从而控制动态内存的长度:指针变量= new 数据类型[长度];
7、new和delete运算符在一起使用时,还可以用于分配和释放多维数组:
指针变量= new 数据类型[i][j];(i,j表示数组的维度)
delete [] 指针变量;
8、new运算符和delete运算符可以和成员函数一起使用:new对象后
调用对象中的成员函数,delete对象前调用成员函数释放相关资源。
9、new和delete运算符还可以用来实现复杂的内存申请和释放操作,
如关联内存的释放等。
10、在大量的程序中使用new和delete操作符,还需要注意异常处理,以保证程序的安全性。
简述this指针的作用一、概述this指针是C++中的一个关键字,它代表当前对象的指针。
在类的成员函数中,使用this指针可以访问当前对象的成员变量和成员函数。
本文将详细介绍this指针的作用。
二、this指针的定义在C++中,每个对象都有一个隐含的指向自身的指针,这个指针就是this指针。
在类成员函数中,可以使用this关键字来访问当前对象。
三、this指针的作用1. 解决命名冲突当类中存在与全局变量或局部变量同名的成员变量时,在成员函数中使用该变量时会出现命名冲突。
此时可以使用this关键字来明确表示要访问的是类中的成员变量而不是全局或局部变量。
2. 返回当前对象在某些情况下,需要返回当前对象本身。
此时可以使用return *this;语句来返回当前对象。
3. 实现链式编程链式编程是一种编程风格,在调用函数后返回自身以便于链式调用其他函数。
例如:```object.func1().func2().func3();```其中,func1()返回object本身,可以直接调用func2();func2()同样返回object本身,可以直接调用func3()。
这样就实现了链式编程。
使用this指针可以方便地实现链式编程。
4. 实现拷贝构造函数和赋值运算符重载在拷贝构造函数和赋值运算符重载中,需要将一个对象的值复制到另一个对象中。
此时可以使用this指针来访问当前对象的成员变量,再将其赋值给另一个对象。
5. 解决多态性问题在多态性中,父类指针指向子类对象时,如果调用子类对象的成员函数,则需要使用this指针来访问子类对象的成员变量和成员函数。
四、使用this指针的注意事项1. this指针只能在成员函数中使用。
2. this指针不能被修改。
3. 在静态成员函数中不能使用this指针。
4. 在全局作用域中不能使用this关键字。
五、总结本文介绍了this指针在C++中的作用。
通过使用this关键字,可以解决命名冲突、返回当前对象、实现链式编程、实现拷贝构造函数和赋值运算符重载以及解决多态性问题等。
C++语言中const关键字用法总结一、const是什么在C/C++ 语言中,const关键字是一种修饰符。
所谓“修饰符”,就是在编译器进行编译的过程中,给编译器一些“要求”或“提示”,但修饰符本身,并不产生任何实际代码。
就const 修饰符而言,它用来告诉编译器,被修饰的这些东西,具有“只读”的特点。
在编译的过程中,一旦我们的代码试图去改变这些东西,编译器就应该给出错误提示。
所以,const修饰符的作用主要是利用编译器帮助我们检查自己代码的正确性。
我们使用con st在源码中标示出“不应该改变”的地方,然后利用编译器,帮助我们检查这些地方是否真的没有被改变过。
如果我们不小心去修改了这些地方,编译器就会报错,从而帮助我们纠正错误。
使用const和不使用cons t,对于最终编译产生的代码并没有影响。
虽然const对于最终代码没有影响,但是尽可能使用const,将帮助我们避免很多错误,提高程序正确率。
二、const可以修饰哪些对象在上面已经提到过了,const是一种修饰符,那它可以作为哪些对象的修饰符呢?下面列举了一些C/C++中用到cons t的地方。
1,const变量2,const指针3,const引用4,const类5,类的const成员变量6,类的const成员函数7,const修饰函数的形参与返回值下面我们分别讨论上面几种情况下,const的用法。
三、const与变量当一个变量被c onst修饰后,具有以下几个特点:1)该变量只能读取不能修改。
(编译器进行检查)2)定义时必须初始化。
3)C++中喜欢用con st来定义常量,取代原来C风格的预编译指令define。
1 const int var; // Error:常量变量"var"需要初始化设定项2 const int var1 = 42;3 var1 = 43; // Error:表达式必须是可以修改的左值上面代码中第一行和第三行都有错误,注释便是编译器给出的错误提示。
对象的指针、this指针、const、new和delete6.3 练习题1.指向对象的指针与指向对象成员的指针有何不同?2.指向成员函数的指针和指向一般函数的指针有何区别?3.对象指针作函数参数与对象作函数参数有何不同?4.对象引用作函数参数与对象指针作函数参数有何区别?5.什么是this指针?它有何作用?6.什么是对象数组?它如何定义?如何赋值?7。
指向对象数组的指针如何定义?如何赋值?8.什么是指针数组?什么是对象指针数组?它们是如何定义的?它们又将如何被赋值?9。
带参数的main(的形式如何?main(有哪些参数?各表示什么意思?10.如何定义一个常量?11.使用const修饰符定义常指针时,const位置有何影响?举例说明,如何定义一个常量指针?12.如何定义常引用?13,什么是类型适应?举例说明在什么情况下会出现类型适应。
14.常成员函数有何特点?在什么情况下需要定义常成员函数?l 5.常数据成员的初始化如何实现?l 6.如何对子对象进行初始化?17.运算符new和delete的功能是什么?它们可以用来创建动态对象和删除动态对象吗?18.使用new和delete创建和删除动态数组的格式如何?19.在例6.17中,程序执行下列语句20.C十十中类型的自动隐式转换有哪些规则?21.构造函数都具有类型转换函数的功能吗?22.什么是转换函数?定义时应注意哪些问题?6.4一、选择填空1.已知一个类A。
(C是指向类A成员函数的指针。
假设类有3个公有成员:void f1(int,void f2(int和int a。
A.A*p;B. int A::*pc=&A::a;C. void A::*pa(;D.A*pp;2.运算符一>*的功能是( 。
A.用来表示指向对象指针对指向类成员指针的操作B.用来表示对象对指向类成员指针的操作C.用来表示指向对象指针对类成员的操作D.用来表示对象类成员的操作3.已知fl(int是类A的公有成员函数,p是指向成员函数f1( 的指针,采用( 是正确的。
A.p=f1;B.p=A::f1;C. p=A::f1(;D.p=fl(;4.已知:P是一个指向类A数据成员m的指针,A1是类A的一个对象。
如果要给m赋值为5,( 是正确的。
A.A1.P=5;B.A1一>P=5;C.A1.*p=5;D.*A1.p=5;5.已知类A中一个成员函数说明如下所示。
void Set(A&a;其中,A&a的含意是( 。
A.指向类A的指针为aB.将a的地址值赋给变量Setc. a是类A的对象引用,用来作函数Set()的形参D. 变量A与a按位与作为函数Set()的参数6.下列关于对象数组的描述中,( 是错误的。
A.对象数组的下标是从o开始的B.对象数组的数组名是一个常量指针C.对象数组的每个元素是同一个类的对象D.对象数组只能赋初值,而不能被赋值7.下列定义中,( 是定义指向数组的指针P。
A. int*p[5];B. int(*p[5];C. (int *p[5]D.int*p[];8.下列说明中Const char * Ptr;ptr应该是( 。
A.指向字符常量的指针B.指向字符的常量指针C.指向字符串常量的指针D.指向字符串的常量指针9.已知:print( 函数是一个类的常成员函数,它无返回值,下列表示中是正确的。
A. void print(const ;B. const void Print( ;C. void const print( ;D. void print (const;10.关于new运算符的下列描述中,( 是错的。
A.它可以用来动态创建对象和对象数组B.使用它创建的对象或对象数组,可以使用运算符delete删除C.使用它创建对象时要调用构造函数D.使用它创建对象数组时必须指定初始值11.关于delete运算符的下列描述中,( 是错的。
A.它必须用于new返回的指针B.它也适用于空指针C.对一个指针可以使用多次该运算符D.指针名前只用一对方括号符,不管所删除数组的维数12.具有转换函数功能的构造函数,应该是( 。
A.不带参数的构造函数B.带有一个参数的构造函数C.带有两个以上参数的构造函数D.默认构造函数二、判断下列描述是否正确,对者划√,错者划×1.指向对象的指针和指向类的成员的指针在表达形式上是不相同的。
2.已知:m是类A的对象,n是类A的公有数据成员,P是指向类A中n成员的指针。
下述两种表示是等价的。
m.n和m.*p3.指向对象的指针与对象都可以作为函数参数,但是使用前者比后者好些。
4.对象引用作函数参数比用对象指针更方便些。
5.对象数组的元素可以是不同类的对象。
6.对象数组既可以赋初值又可以赋值。
7.指向对象数组的指针不一定必须指向数组的首元素。
8.一维对象指针数组的每个元素应该是某个类的对象的地址值。
9.const char*p说明了p是指向字符串常量的指针。
10.一个能够更新的变量使用在一个不能被更新的环境中是不破坏类型保护的,反之亦然。
11.一个类的构造函数中可以不包含对其子对象的初始化。
12.转换函数不是成员函数,它是用来进行强制类型转换的。
三、分析下列程序的输出结果1.#include<iostream.h>class A{public:A(;A(int i,int j;~A(;void Set(int i,int j{a=i;b=j;}private:int a,b;};A::A({a=b=O;cout<<”Default constructor called.\n”;}A ::A(int i,int j{a=i;b=j;cout<<”Constructor:a=”<<a<<”,b=”<<b<<endl;}A ::~A({ cout<<”Destructor called.a=”<<a<<”,b=”<<b<<endl; }void main({cout<<”Starting1:\n”;A a[3];for(int i=0;i<3;i十十a[1].Set(2*i十1,(i十1* 2;cout<<”Endingl…\n”;cout<<”Starting2…\n”;A b[3]={A(5,6,A(7,8,A(9,l0};cout<<”Ending2…\n”;}分析:程序中出现了构造函数重载和对象数组等语法现象.并给了对象数组赋值和赋初值的方法。
2.#includeClass B{int x,y;public:B(;B(int i;B(int i,int j;~B(;void Print(;};B::B({ x=y=0;Cout<<”Default constructtorl called.\n”;}B::B(int i{x=i;y=0;Cout<<”Donstructtorl called.\n”;}B::B(int i, int j{x=i;y=j;Cout<<”Donstructtorl called.\n”;}` B:: ~B({ cout<<”Donstructtor called.\n”;}void B::Print({ cout<<”x=”< ” y= ” <}Void main({B *p;Prt=new B[3];Prt[0]=B(;Prt[1]=B(5;Prt[2]=B(2,3;For(int i=0;i<3;i++Prt[i]=Print(;Delete[]ptr;}该程序的执行结果?3.#includeClass A{public;A(int i=o{m=i;cout<<”Construc tor called.”<<m<<endl;} void Set(int i { m=i;}void Print(const{cout<<m<<endl;}~A({cout<<”Destructor called.”<<m<<endl;}private:int m;};void main({const N=5;A my;my=N;my.Print(;}分析:该程序中出现了常成员函数Frint(的语法现象。
它的出现是为了满足主函数my.Print(的需要,这里的my实际上是一个常对象,因为它的值为N的值,N是一个整型量。
语句my=N;是将一个常整型量通过调用一个参数的构造函数转换为一个对值后,再赋值给对象my的。
因此,这里先调用构造函数,后调用析构函数。
4.#include<iostream.h>Class A{public:A(int i=O{m=i;cout<<”Constructor called.”<<m<<endI;}void Set(int i{m=i;}void Print( const { cout<<m<<endl;}~A({cout<<”Destructor called.”<<m<<endl;}private:int m;};void fun(const A&c{c.print( ;}void main({fun(5;}分析:该程序中出现了对象引用作函数参数的语法现象。
在主函数中,调用函数实参为常量5,这时要调用一个参数的构造函数,将5转换为A类的一个对象,给形参引用,该对象将被析构。
请读者按下列要求对原程序进行修改,然后再调试,看输出结果有何变化?(1去掉类A中定义的成员函数Set(。
(2将一般函数fun(后形参改为对象。
5.#include<iostream.h>Class complex{public:complex(;complex(double real;complex(double real,double imag;void Print(;void Set(double r,double i;private:double reaI,imag;};complex::complex({Set(0,0,0.0;cout<<”Constructor:real="<}complex::complex(double real,double imag{Set(real,imag;cout<<”Constructor: real=”<<real<<“,imag=”<<imag<<endl;void complex::Print({if(imag<Ocout<<real<<imag<<’i’<<endl;elsecout<<real<<’十’<<imag<<’i’<<endl;void complex::Set(double r,double i{real:=r:imag:=i;}void rnain({complex c1;complex c2(6.8;complex c3(5.6,7.9;c1.Print( ;c2.Print( ;c3.Print( ;c1=complex(1.2,3.4;c2:=5:c3;complex(;c1.Print(;c2.Print(;c3.Print( ;}分析:该程序中类complex是用来描述复数的一个类,它有实部和虚部两个数据成员。