C++基础_03

来源:互联网 发布:数据分析的基本流程 编辑:程序博客网 时间:2024/05/23 02:01

构造函数和析构函数执行的顺序

#include <iostream>#include <stdlib.h>#include <string.h>#include <ctype.h>using namespace std;class Test{public:    Test(char * name){        memset(this->name,0,sizeof(this->name));        strcpy(this->name,name);        cout<<"Test()->Name = "<<name<<endl;    }    ~Test(){        cout<<"~Test()->Name = "<<name<<endl;    }protected:private:    char name[64];};void run(){   //#1    Test t1("t1");    Test t2("t2");}   //#2void run2(){//#1    Test t1("t1");}//#2int main(int argc, char *argv[]){   run2()// #1 -> t1的构造函数 -> #2 -> t1的析构函数    run();// #1 -> t1的构造函数 -> t2的构造函数 -> #2 -> t2的析构函数 -> t1的析构函数     return 0;}

构造函数的调用时机

#include <iostream>using namespace std;class Test{public:    //构造函数分类:无参,有参和拷贝    //无参构造函数    Test(){        cout<<"Test(void)"<<endl;    };    //带参构造函数    Test(int a){        cout<<"Test(int )"<<endl;    }    Test(int a,int b){        cout<<"Test(int ,int )"<<endl;    }    //拷贝构造函数    Test (const Test &object){        cout<<"Test(const Test & )"<<endl;    }};int main(int argc, char *argv[]){    //如果类没有提供构造函数,C++会默认提供一个无参构造函数和一个拷贝构造函数    //调用无参构造函数    Test t1;//OK//    Test t1(); //Error    //调用带参构造函数    Test t2(5);//OK    Test t3 = (4,5);//OK ==> (4,5)会被当成逗号表达式,最终调用的其实是 Test(int),若是不存在[Test(int)]则编译器报错    //使用匿名对象调用构造函数    Test t4 = Test(1,2); //OK ==> Test(int ,int)     //调用拷贝构造函数    Test t5(10,20);    Test t6 = t5;//调用的是拷贝构造函数    Test t7(t5);//调用的是拷贝构造函数    Test one,two;    one = two;//调用的是赋值函数,没有调用构造函数    return 0;}

拷贝构造函数的调用时机

#include <iostream>using namespace std;class Location{private:    int x;    int y;public:    Location(){        cout<<"Test()"<<endl;    }    ~Location(){        cout<<"~Test()"<<endl;    }    Location(int x,int y){        cout<<"Location(int ,int )"<<endl;        this->x = x;        this->y = y;    }    Location (const Location & location){        this->x = location.x;        this->y = location.y;        cout<<"Location(const Location & location)"<<endl;    }public:    void show(){        cout<<"x = "<<x<<" y = "<<y<<endl;    }};void copy(Location L)//传参过程执行的是拷贝构造函数{                               //#1    L.show();}                               //#2void run() {                               //#1    Location L_one(100,200);    //#2    copy(L_one);                //#3}                               //#4/*run函数     run#1 -> run#2:L_one的构造函数 -> run#3:copy(L_one)[L_one执行拷贝构造函数] -> copy:#1 -> copy#2:L的析构函数 ->  run#4:L_one的析构函数 *///当函数的返回值是一个类的类型的时候[类的类型,仅指(Location),并非(Location * 或 Location &)],函数 return 的时候也会执行拷贝构造函数//这里仅指VS2012的编译器,GCC并不支持这一做法Location getLocation(){                               //#1    Location Lo(7,8);    return Lo;                  //#2 //函数的返回值是一个元素(class)C++编译器会返回以一个新的匿名对象}                               //#3void run2(){                    //#1    getLocation();  // 函数返回的时候没有(Location)对象被接收  -> "[匿名Location对象]~Test()"}                               //#2/*run2函数    VS2013:        run2#1: -> getLocation#1 -> getLocation#2[                                                    1):Lo执行拷贝构造函数 Test(cosnt Test &) 创建一个匿名的Location对象.                                                    2):Lo执行析构函数 ~Test()                                                 ] -> getLocation#3: 返回匿名Location对象 -> run2#2:匿名Location对象执行析构函数 ~Test()     QT5.7:        run2#1: -> getLocation#1 -> getLocation#2 -> getLocation#3: 返回自身(Lo对象) -> run2#2:Lo 对象执行析构函数 ~Test()*/void run3(){                    //#1    Location LoL = getLocation();//#2  // 函数返回时有匿名对象接收 -> C++编译器会把匿名对象直接转成LoL,并不会执行拷贝构造函数    LoL.show();}                               //#3 /*run3函数    VS2013:        run3#1: -> getLocation#1 -> getLocation#2[                                                    1):Lo执行拷贝构造函数 Test(cosnt Test &) 创建一个匿名的Location对象.                                                    2):Lo执行析构函数 ~Test()                                                 ] -> getLocation#3: 返回匿名Location对象 -> run3#2:匿名Location对象直接转成LoL对象(不执行拷贝构造函数)                                                    -> run3#3:LoL执行析构函数 ~Test()    QT5.7:        run3#1: -> getLocation#1 -> getLocation#2 -> getLocation#3: 返回自身(Lo对象) -> run3#2:Lo 对象直接转成LoL对象(不执行拷贝构造函数) -> run3#3:LoL执行析构函数 ~Test()*/void run4(){                //#1    Location Lol(4,5); //对象已经初始化    Lol.show();    Lol = getLocation();    //#2  //匿名对象会执行赋值操作直接复制给(Lol)然后执行析构函数    Lol.show();}                           //#3/*run4函数    VS2013:        run4#1: -> getLocation#1 -> getLocation#2[                                                    1):Lo执行拷贝构造函数 Test(cosnt Test &) 创建一个匿名的Location对象.                                                    2):Lo执行析构函数 ~Test()                                                 ] -> getLocation#3: 返回匿名Location对象                                                    -> run4#2:匿名Location对象直接将值复制给(Lol),然后执行析构函数 ~Test()                                                    -> run4#3:Lol执行析构函数 ~Test()    QT5.7:        run4#1: -> getLocation#1 -> getLocation#2 -> getLocation#3: 返回自身(Lo对象) -> run4#2:Lo 对象直接将值直接复制给(Lol)然后执行析构函数 ~Test()                -> run4#3:LoL执行析构函数 ~Test()*/int main(int argc, char *argv[]){//    run();//    run2();//    run3();//    run4();    return 0;}

C++中的浅拷贝

#include <iostream>#include <stdlib.h>#include <string.h>#include <ctype.h>using namespace std;class Name{public:    Name (const char * name){        this->length = strlen(name);        this->name = (char *)malloc(this->length + 1);        strcpy(this->name,name);    }    ~Name(){        if (this->name != NULL){            free(this->name);            this->name = NULL;            this->length = 0;        }    }    //解决方案:    /*    Name (const Name & N){        this->length = N.length;        this->name = (char *)malloc(this->length + 1);        strcpy(this->name,N.name);    }    */public:    void show(){        cout<<"Name = "<<this->name<<endl;    }private:    char * name;    int length;};void run(){    Name N_1("yzh"); // N_1执行构造函数初始化    {        Name N_2 = N_1;        // 在没有 [解决方案] 的前提下        /*        N_2执行Name类默认的拷贝构造函数来初始化(浅拷贝),则        N_2的成员变量Name并未重新分配内存,而是指向了N_1的Name所在的内存,即N_1的Name和N_2的Name指向的是同一片内存        当程序执行到[ #2 ]处的时候,N_2执行析构函数,N_2的Name所处的内存被回收        当在[ #2 ]之后再次执行[ N_1.show(); ]的时候,会因为内存已经被回收而导致程序出现错误        */        N_1.show();        N_2.show(); //Name = yzh;    }//#2    N_1.show(); // 不存在[解决方案]的时候 Name = 垃圾值}int main(int argc, char *argv[]){    run();    return 0;}

构造函数初始化列表:
1)B类中组合了A类对象
2)A类设计了构造函数

#include <iostream>using namespace std;class A{public:    A(int a){        cout<<"A = "<<a<<endl;        this->a = a;    }    ~A(){        cout<<"~A = "<<a<<endl;    }private:    int a;};//B类中含有A类的对象class B{public:    //利用B类构造函数的初始化列表来初始化A类    B(int a,int b):A_two(b),A_one(a) //初始化列表顺序    {        this->a = a;        this->b = b;        cout<<"B"<<endl;    }    ~B(){        cout<<"~B"<<endl;    }private:    int a;    int b;    //定义的顺序    A A_one;    A A_two;};void run(){    B b(1,2);    /*        1)按照定义的顺序通过构造函数列表执行A类的构造函数,A类的构造函数执行完毕之后才是B类的构造函数        2)构造函数的执行顺序和析构函数执行的顺序相反        A_one构造函数 -> A_two构造函数 -> B 的构造函数 -> B 的析构函数 -> A_two的析构函数 -> A_one的析构函数    */}int main(int argc, char *argv[]){    run();    return 0;}

构造函数列表执行顺序

#include <iostream>using namespace std;class A{public:    A(int a,int b){        this->a = a;        this->b = b;        cout<<"A = "<<a<<" B = "<<b<<endl;    }    ~A(){        cout<<"~A"<<endl;    }private:    int a;    int b;};class B{public:    B(int a,int b):A_1(a,b),A_2(a,b),m(b),n(a)    {        cout<<"M = "<<m<<" N = "<<n<<endl;    }    B(const B & sb):A_1(sb.m,sb.n),A_2(sb.n,sb.m)    {        this->m = sb.m;        this->n = sb.n;        cout<<"B (const B &)"<<endl;    }    ~B(){        cout<<"~B"<<endl;    }public:    void show(){        cout<<"SHOW: M = "<<m<<" N = "<<n<<endl;    }private:   int m;   int n;   A A_1;   A A_2;};void getShow(B sb){    sb.show();}void run(){    B sb(22,99);    getShow(sb);}int main(int argc, char *argv[]){    run();/*//从B的普通构造函数进入A = 22 B = 99  A_1构造A = 22 B = 99  A_2构造M = 99 N = 22  sb构造//从B的拷贝构造函数进入A = 99 B = 22  A_1构造A = 22 B = 99  A_2构造B (const B &)  sb的拷贝构造SHOW: M = 99 N = 22 sb的show函数//析构函数逆序执行~B~A~A~B~A~A*/    return 0;}

匿名对象的生命周期

#include <iostream>using namespace std;class Test{public:  Test(){      cout<<"Test"<<endl;  }  ~Test(){      cout<<"~Test()"<<endl;  }};void run(){    cout<<"#1"<<endl;    Test();//初始化一个匿名对象    cout<<"#2"<<endl;    Test t;//初始化一个名为t的对象//    Test t();//Error    cout<<"#3"<<endl;}/*    #1 -> "Test()" -> "~Test()" -> #2 -> "Test()" -> #3 -> "~Test()"    //匿名对象会在 #2 之前被析构掉    //t对象会在run函数的"}"结束之后被析构掉*/int main(int argc, char *argv[]){    run();    return 0;}

构造函数调用构造函数

#include <iostream>using namespace std;class Test{public:    Test(int a,int b){        this->a = a;        this->b = b;        Test(a,b,100); //产生一个匿名对象,构造之后马上被析构掉了,根本无法为变量c赋值    }    Test(int a,int b,int c){        this->a = a;        this->b = b;        this->c = c;    }    ~Test(){        cout<<"~Test()"<<endl;    }public:    void show(){        cout<<"SHOW: A = "<<a<<" B = "<<b<<" C = "<<c<<endl;    }private:    int a;    int b;    int c;};void run(){    Test t(1,2);    t.show(); //c是一个垃圾值}int main(int argc, char *argv[]){    run();    return 0;}
0 0
原创粉丝点击