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
- java基础总结_03
- C++基础_03
- javascript基础_03
- Qt 消息基础相关_03
- Java从基础开始_03面向对象
- 面向对象的基础篇_03
- [Web基础开发-JSP基础语法]包含指令_03
- 黑马程序员_Java基础_语句函数_03
- 黑马程序员_Java基础_面向对象_03
- 面试基础_03实现strcpy、strcat、strcmp、strlen
- JavaScript基础_03样式引入与结构语句
- Linux环境下C语言编程实践_03
- 初始化_03
- 整理_03
- 黑马程序员--JAVA基础_03(继承、final修饰符、抽象、模版方法设计模式)
- Java千百问_03基础语法(012)_transient关键字有什么用
- Java千百问_03基础语法(013)_>、>>、>>>有什么区别
- Java千百问_03基础语法(014)_volatile关键字有什么用
- C语言 求两个数的最大公约数 (算法)--辗转相减法、辗转相除法
- 跟我学Redis 2.3 Jedis的基本操作之Set
- 装饰器模式
- 第5周项目1 -建立顺序栈算法库
- 统一li高度以最大的为基准的自适应高度
- C++基础_03
- 跟我学Redis 2.4 Jedis的基本操作之Sorted Set
- MVC简介
- java、jsp连接数据库,可当模板
- 稳定排序和不稳定排序
- JavaScript创建对象的四种方式
- REDIS 学习(10)流程图解使用redis实现分布式锁
- 跟我学Redis 2.5 Jedis的基本操作之Hash
- HTTP & RESTFUL