0815,析构函数,拷贝构造函数,赋值运算符函数


来自同济医院的问候

目录

01:对象创建

001.cc

003size.cc 

02:对象销毁

004pointer.cc

005destroytime.cc

03:本类型对象的复制

3.1 拷贝构造函数

006cp.cc

007cptime.cc

008recursion.cc

009rightleft.cc

3.2 赋值运算符函数

010thispointer.cc

 011operator.cc

3.3 三合成原则

作业喵:

01,关于对象概念的描述中,( )是错误的。   A

02,有关析构函数的说法不正确的是( )  C

03,对类的构造函数和析构函数描述正确的是( )。  A

04,有关类的说法不正确的是____。    D

05,一个空类对象占据的空间有多大?会自动创建哪些函数呢?

06,什么情况下,会调用拷贝构造函数?

07,什么是拷贝构造函数,其形态是什么,参数可以修改吗?

08,什么是赋值运算符函数,其形态是什么?什么情况下需要手动提供赋值运算符函数呢?

09,写出下面程序的运行结果()

10,设已经有A,B,C,D 4个类的定义,程序中A,B,C,D析构函数调用顺序为? ABDC(坏)

11,定义一个学生类,其中有3个数据成员:学号、姓名、年龄,以及若干成员函数。同时编写main函数,使用这个类,实现对学生数据的复制、赋值与输出。

01:对象创建

001.cc

#include <iostream>
using std::cout;
using std::endl;

class Point{
public:
    Point()
        :_ix(0),_iy(0)
    {cout<<"Point()"<<endl;}
    Point(int x,int y=1)
        :_ix(x),_iy(y)
    {cout<<"Point(int ,int)"<<endl;}
    //不是严格意义的初始化,本质是赋值
    /* Point(int x,int y){ */
    /*     _ix=x; */
    /*     _iy=y; */
    /*     cout<<"Point(int ,int )"<<endl;} */
    void print(){ cout<<_ix<<"\t\t"<<_iy<<endl; }
private:
    int _ix;
    int _iy;
};
void test(){
    Point pt1;
    Point pt2(5);
    Point pt(1,2);
    pt1.print();
    pt2.print();
    pt.print();
}

int main(void)
{
    test();
    return 0;
}

003size.cc 

#include <iostream>
using std::cout;
using std::endl;

#pragma pack(4)

class A{
    int _num;
    double _price;
};
class B{
    int _num;
    int _price;
};
class C{
    int _num;
    int _num1;
    double _price;
};
class D{
    int _num;
    double _price;
    int _num1;
};
class E{
    double _e;
    char _eArr[20];
    double _e1;
    int _e2;
};
class F{
    char _fArr[20];
};
class G{
    int num;
};
class H{
    char _gArr[20];
    int _g1;
    int _g2;
};
class I {};
void test(){
    cout<<sizeof(A)<<endl;
    cout<<sizeof(B)<<endl;
    //16 8
    cout<<sizeof(C)<<endl;
    cout<<sizeof(D)<<endl;
    //16 24
    cout<<sizeof(E)<<endl;
    cout<<sizeof(F)<<endl;
    //48 24
    cout<<sizeof(G)<<endl;
    cout<<sizeof(H)<<endl;

    cout<<endl;
    I i1,i2;
    cout<<&i1<<" "<<&i2<<endl;
    cout<<sizeof(I)<<endl;
}

int main(void)
{
    test();
    return 0;
}

02:对象销毁

004pointer.cc

#include <iostream>
#include <string.h>
using std::cout;
using std::endl;

class Computer{
public:
    Computer(const char* brand,double price)
        : _brand(new char[strlen(brand)+1]())
        , _price(price)
    {
        strcpy(_brand,brand);// 否则没有赋值喵,不输出
        cout<<"Computer"<<endl;}
    ~Computer(){
        if(_brand){
            delete []  _brand;  //coution
             _brand=nullptr;   //加上,信任行为喵
        }
        cout<<"~Computer"<<endl;
    }
    void printBrandPrice(){
        cout<<"brand:"<<_brand<<"\t\t";
        cout<<"price:"<<_price<<endl;
    }
private:
    /* char _brand[20]; */
    char* _brand;
    double _price;
};

void test(){
    Computer pc("dell",20000);
    pc.printBrandPrice();

    //对象销毁时一定会调用析构函数,析构函数执行完,对对象没有被销毁
    //defecate indiscriminately 
    pc.~Computer();
    /* pc.printBrandPrice();  //locked */
    cout<<"over "<<endl;
}
void test01(){
    const char *p="i love xixi";
    int * pp=nullptr;
    cout<<p<<endl;
    cout<<pp<<endl; //0
    p=nullptr;
    //C++会自动访问char*类型指针,此处访问了空指针
    /* cout<<p<<endl; */
    cout<<"OK OK OK"<<endl;
}
int main(void)
{
    test();
    test01();
    return 0;
}

005destroytime.cc

#include <iostream>
#include <string.h>
using std::cout;
using std::endl;

class Computer{
public:
    Computer(const char* brand,double price)
        : _brand(new char[strlen(brand)+1]())
        , _price(price)
    {
        strcpy(_brand,brand);// 否则没有赋值喵,不输出
        cout<<_brand<<"\t\t"<<"Computer"<<endl;
    }
    ~Computer(){
        cout<<_brand<<"\t\t";
        if(_brand){
            delete []  _brand;  //coution
             _brand=nullptr;   //加上,信任行为喵
        }
        cout<<"~Computer"<<endl;
    }
    void printBrandPrice(){
        cout<<_brand<<"\t";
        cout<<_price<<endl;
    }
private:
    /* char _brand[20]; */
    char* _brand;
    double _price;
};

Computer pc_static("huipu__1",40000);
void test(){
    Computer pc("dell__2",20000);
    pc.printBrandPrice();

    Computer pc_kaixin("honor__3",0);
    pc_kaixin.printBrandPrice();

    static Computer pc_jiajia("vsus__4",10000);
    pc.printBrandPrice();
    pc_jiajia.printBrandPrice();
    pc_static.printBrandPrice();

    Computer* p_new=new Computer("lengion__5",8000);
    p_new->Computer::printBrandPrice();
    delete p_new;
    p_new=nullptr;
    //坏  后创建的先销毁
}
void test01(){
}
int main(void)
{
    test();
    test01();
    return 0;
}

03:本类型对象的复制

3.1 拷贝构造函数

006cp.cc

#include <iostream>
#include <string.h>
using std::cout;
using std::endl;

class Computer{
public:
    Computer(const char* brand,double price)
        : _brand(new char[strlen(brand)+1]())
        , _price(price)
    {
        strcpy(_brand,brand);// 否则没有赋值喵,不输出
        cout<<_brand<<"\t\t"<<"Computer"<<endl;
    }
    Computer(const Computer & pc)
        : _brand(new char[strlen(pc._brand)+1]())
        , _price(pc._price)
    {
        strcpy(_brand,pc._brand);// 否则没有赋值喵,不输出
        cout<<_brand<<"\t\t"<<"Copy  Computer"<<endl;
    }
    ~Computer(){
        cout<<_brand<<"\t\t";
        if(_brand){
            delete []  _brand;  //coution
             _brand=nullptr;   //加上,信任行为喵
        }
    }
    void printBrandPrice(){
        cout<<_brand<<"\t";
        cout<<_price<<endl;
    }
private:
    /* char _brand[20]; */
    char* _brand;
    double _price;
};

void test(){
    int x=10;
    int y=x;
    cout<<x<<endl;
    cout<<y<<endl;

    Computer pc("dell",20000);
    pc.printBrandPrice();
    /* Computer pp=pc; */
    Computer pp(pc);
    pp.printBrandPrice();
    //坏,double free
    //original cpy浅拷贝喵

}


int main(void)
{
    test();
    return 0;
}

007cptime.cc

#include <iostream>
using std::cout;
using std::endl;

class Point{
public:
    Point()
        :_ix(0),_iy(0)
        {cout<<"Point()"<<endl;}
    Point(int x,int y=1)
        :_ix(x),_iy(y)
        {cout<<"Point(int ,int)"<<endl;}
    Point(const Point & p)
        :_ix(p._ix),_iy(p._iy)
        {cout<<"Point(Point &)"<<endl;}
    void print(){ cout<<_ix<<"\t\t"<<_iy<<endl; }
private:
    int _ix;
    int _iy;
};

//Point p=pt3
void func(Point p){
    p.print();
}
//第二种调用时机 实参和形参都是对象(用实参初始化形参的过程也会调用拷贝构造)
//避免多余复制,写成引用形式
void func01(Point &  p){
    p.print();
}
Point pp(258,258);
Point func02(){ return pp; }
//函数的返回值时对象时,执行return语句会调用拷贝构造
Point & func03(){ return pp; }
//避免这次复制可以将返回值写为引用
//caution live_time

void test(){
    Point pt1;
    Point pt2(5);
    Point pt(1,2);
    Point pt3(pt1);
    //第一种调用时机 初始化

    cout<<endl;
    func(pt3);
    func01(pt3);
    //第2种调用时机 

    cout<<endl;
    func03().print();
    func02().print();
    //第3种调用时机 

    /* pt1.print(); */
    /* pt2.print(); */
    /* pt.print(); */
    /* pt3.print(); */
}

int main(void)
{
    test();
    return 0;
}

008recursion.cc

#include <iostream>
using std::cout;
using std::endl;

class Point{
public:
    Point()
        :_ix(0),_iy(0)
        {cout<<"Point()"<<endl;}
    Point(int x,int y=1)
        :_ix(x),_iy(y)
        {cout<<"Point(int ,int)"<<endl;}
    /* Point(const Point & p) */
    /*     :_ix(p._ix),_iy(p._iy) */
    /*     {cout<<"Point(Point &)"<<endl;} */

    /* Point( Point & p) */
    /*     :_ix(p._ix),_iy(p._iy) */
    /*     {cout<<"Point(Point &)"<<endl;} */
    //保证右操作数不被修改,为了能够复制临时对象的

    Point(const Point  p)
        :_ix(p._ix),_iy(p._iy)
        {cout<<"Point(Point &)"<<endl;}
    //const Point p=pt1,触发拷贝构造函数,陷入递归拷贝喵
    void print(){ cout<<_ix<<"\t\t"<<_iy<<endl; }
private:
    int _ix;
    int _iy;
};


void test(){
    Point pt1(30,50);
    Point pt3(pt1);
    pt1.print();
    /* pt3.print(); */
    //error 

    /* Point pt4=Point(20,20); */
    /* pt4.print(); */
    //坏,我的好想能跑
}

int main(void)
{
    test();
    return 0;
}

009rightleft.cc

#include <iostream>
using std::cout;
using std::endl;

class Point{
public:
    Point()
        :_ix(0),_iy(0)
        {cout<<"Point()"<<endl;}
    Point(int x,int y=1)
        :_ix(x),_iy(y)
        {cout<<"Point(int ,int)"<<endl;}
    Point(const Point & p)
        :_ix(p._ix),_iy(p._iy)
        {cout<<"Point(Point &)"<<endl;}
    void print(){ cout<<_ix<<"\t\t"<<_iy<<endl; }
private:
    int _ix;
    int _iy;
};


void test(){
    int a=10;
    int b=20;
    cout<<&a<<endl;
    cout<<&(++a)<<endl;
    //左值  能取地址
    /* cout<<&(a++)<<endl; */
    /* cout<<&(a+b)<<endl; */
    //右值 不能 (临时变量/匿名对象,临时对象,字面值
    //&1  存在与指令系统,不存在内存中

    Point pt(1,1);
    cout<<&pt<<endl;

    cout<<endl;
    int & ref=a;
    const int & ref1=b;
    /* int & ref2=a+b; */
    //no const=left
    //const = left or right
    const int & ref4=a+b;
    /* printf("%p\n",ref); */
    /* printf("%p\n",ref1); */
    /* printf("%p\n",ref4); */
}

int main(void)
{
    test();
    return 0;
}

3.2 赋值运算符函数

010thispointer.cc

#include <iostream>
using std::cout;
using std::endl;

class Point{
public:
    Point()
        :_ix(0),_iy(0)
        {cout<<"Point()"<<endl;}
    Point(int x,int y=1)
        :_ix(x),_iy(y)
        {cout<<"Point(int ,int)"<<endl;}
    Point(const Point & p)
        :_ix(p._ix),_iy(p._iy)
        {cout<<"Point(Point &)"<<endl;}
    //Point * const this
    //不能修改指向,”本对象“的地址
    //隐藏成员函数参数
    Point & operator=(const Point & p){
        cout<<"operator="<<endl;
        /* this->_ix=p._ix; */
        /* this->_iy=p._iy; */
        _ix=p._ix;_iy=p._iy;
        return *this;
    }
    void print(){ cout<<_ix<<"\t\t"<<_iy<<endl; }
private:
    int _ix;
    int _iy;
};


void test(){
    Point p(10,30);
    Point p1;
    p1.print();
    p1=p;
    /* pt.operator=(pt2);//本质形式 */
    p1.print();

    cout<<endl;
    int x=10,y=100;
    cout<<&(x=y)<<endl;
    cout<<&x<<endl;
}

int main(void)
{
    test();
    return 0;
}

 011operator.cc

#include <iostream>
#include <string.h>
using std::cout;
using std::endl;

class Computer{
public:
    Computer(const char* brand,double price)
        : _brand(new char[strlen(brand)+1]())
        , _price(price)
    {
        strcpy(_brand,brand);// 否则没有赋值喵,不输出
    }
    Computer(const Computer & pc)
        : _brand(new char[strlen(pc._brand)+1]())
        , _price(pc._price)
    {
        strcpy(_brand,pc._brand);// 否则没有赋值喵,不输出
    }
    Computer & operator=(const Computer & c){
        cout<<"operator ="<<endl;
        if(this!=&c){
            //1 考虑自赋值的情况
            delete [] _brand;
            //2  回收原本管理的堆空间
            _brand=new char[strlen(c._brand)+1]();
            strcpy(_brand,c._brand);
            //3  深拷贝
            _price=c._price;
        }
        return *this;
        //4  返回本对象
    }
    ~Computer(){
        if(_brand){
            delete []  _brand;  //coution
             _brand=nullptr;   //加上,信任行为喵
        }
    }
    void printBrandPrice(){
        cout<<_brand<<"\t";
        cout<<_price<<endl;
    }
private:
    /* char _brand[20]; */
    char* _brand;
    double _price;
};

void test(){

    Computer pc("dell",20000);
    Computer pc1("cici",20000);
    pc.printBrandPrice();
    /* Computer pp=ps; */
    Computer pp(pc);
    pp.printBrandPrice();
    //坏,double free
    //original cpy浅拷贝喵
    
    pc=pc;
    pc.printBrandPrice();
    pc=pc1;
    pc.printBrandPrice();

}


int main(void)
{
    test();
    return 0;
}

3.3 三合成原则

作业喵:

01,关于对象概念的描述中,( )是错误的。   A

  • A对象就是C语言中的结构体

  • B对象是状态和操作的封装体

  • C对象之间的信息传递是通过消息进行的

  • D对象是某个类的一个实例

02,有关析构函数的说法不正确的是( )  C

  • A析构函数有且只有一个

  • B析构函数无任何函数类型

  • C析构函数和构造函数一样可以有形参

  • D析构函数的作用是在对象被撤销时收回先前分配的内存空间

03,对类的构造函数和析构函数描述正确的是( )。  A

  • A构造函数可以重载,析构函数不能重载

  • B构造函数不能重载,析构函数可以重载

  • C构造函数可以重载,析构函数也可以重载

  • D构造函数不能重载,析构函数也不能重载

04,有关类的说法不正确的是____。    D

  • A类是一种用户自定义的数据类型

  • B只有类中的成员函数才能存取类中的私有数据

  • C在类中,如果不作特别说明,所有的数据均为私有类型

  • D在类中,如果不作特别说明,所有的成员函数均为公有类型

05,一个空类对象占据的空间有多大?会自动创建哪些函数呢?

空类:1个字节,仅仅是编译器的一种占位机制

自动创建的函数:默认无参构造,默认析构,默认拷贝构造(浅拷贝),赋值运算符函数(浅拷贝的那种喵)

06,什么情况下,会调用拷贝构造函数?

1,用已经存在的对象给新建的对象初始化

(以下为不看代码十分抽象内容)

2,函数参数(实参和形参的类型都是对象),形参与实参结合时(实参初始化形参)
避免不必要的拷贝,可以使用引用作为参数

3,函数的返回值是对象(return 会 copy)
避免多余拷贝,用引用作为返回值,确保返回值的生命周期大于函数的生命周期

07,什么是拷贝构造函数,其形态是什么,参数可以修改吗?

1,用一个已经存在的同类型的对象来初始化新对象的 构造函数

2,类名  (const 类名 & )

3,不可以
3.1  不可以去掉引用符号(遇到第二种调用时机“形参实参都是对象,用实参初始化形参”的时候,会再一次调用拷贝构造,导致递归调用
3.2  不可以去掉const   (1,确保右操作数的数据成员不会被改变,2,为了能够赋值临时对象的内容,非const引用不能绑定临时变量)

08,什么是赋值运算符函数,其形态是什么?什么情况下需要手动提供赋值运算符函数呢?

1,用已经创建的对象给另一个对象赋值的时候,会调用赋值运算函数(没有自定义时,系统会提供一个默认版本(浅拷贝版本))

2,类名 & operator =   (const 类名 &)

3,当拷贝构造,析构函数,赋值运算符手动定义了其中任何一个,其他两个也都需要手动定义

09,写出下面程序的运行结果()

class Sample 
{
	int i;
public:
	Sample();
	Sample(int val);
	void Display();
	~Sample();
};

Sample::Sample() 
{
    cout << "Constructor1" << endl;
    i=0;
}

Sample::Sample(int val) 
{
    cout << "Constructor2" << endl;
    i=val;
}

void Sample::Display() 
{
    cout << "i=" << i << endl;
}

Sample::~Sample() 
{
    cout << "Destructor" << endl;
}

int main() 
{
    Sample a, b(10);
    a.Display();
    b.Display();
	 
    return 0;
}

Constructor1
Constructor2
i=0
i=10
Destructor
Destructor 

10,设已经有A,B,C,D 4个类的定义,程序中A,B,C,D析构函数调用顺序为? ABDC(坏)

C c;
int main()
{
    A *pa=new A();
    B b;
    static D d;
    delete pa;
    return 0;
}

A  B  D  C  (坏,后创建的先销毁

1,堆对象,delete删除时

2,全局对象,整个程序结束时

3,静态对象,整个程序结束时

4,局部对象,程序离开局部对象的作用域时

11,定义一个学生类,其中有3个数据成员:学号、姓名、年龄,以及若干成员函数。同时编写main函数,使用这个类,实现对学生数据的复制、赋值与输出。

#include <iostream>
#include <string.h>
using std::cout;
using std::endl;

class Student{
public:
    Student(int id,int age,const char* name)
        :_id(id),_age(age)
        ,_name(new char[strlen(name)+1]())
        {strcpy(_name,name);}
    Student(const Student & s)
        :_id(s._id),_age(s._age)
        ,_name(new char[strlen(s._name)+1]())
        {strcpy(_name,s._name);}
    Student & operator=(const Student & s){
        if(this!=&s){
            _id=s._id;_age=s._age;
            delete [] _name;
            _name=new char[strlen(s._name)]();
            strcpy(_name,s._name);
        }
        return *this;
    }
    ~Student(){
        cout<<_name<<" ";
        if(_name){
            delete [] _name;
            _name=nullptr;
        cout<<"love xixi"<<endl;
        }
    }
    void printStudent(){
        cout<<_id<<"\t"<<_age<<"\t"<<_name<<endl;
    }
private:
    int _id;
    int _age;
    char* _name;
};
void test(){
    Student jia(1,21,"jiajia");
    jia.printStudent();
    Student kai(1,21,"kaixin");
    jia.printStudent();
    Student hui(kai);
    hui.printStudent();
    hui=jia;
    hui.printStudent();
}

int main(void)
{
    test();
    return 0;
}

1    21    jiajia
1    21    jiajia
1    21    kaixin
1    21    jiajia
jiajia love xixi
kaixin love xixi
jiajia love xixi     //只调用了三次析构函数喵    是我  en~~~?

  • 16
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值