`
k_lb
  • 浏览: 842877 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论
  • kitleer: 据我所知,国内有款ETL调度监控工具TaskCTL,支持ket ...
    kettle调度

复制构造函数(今天开始学习c++了)身为码农,不会c++我像话吗

 
阅读更多

转自:百度百科http://baike.baidu.com/view/2329038.htm


复制构造函数,直接初始化,复制初始化,赋值,临时对象

  复制构造函数应弄清的几个问题:何时调用复制构造函数,复制构造函数有何功能,为什么要定义自已的复制构造函数。
  1.复制构造函数:当用户没有定义自已的复制构造函数时系统将生成一个默认的复制构造函数。当按值传递对象时,就会创建一个形参的临时对象,然后调用复制构造函数把临时对象的值复制给实参。
  2.默认复制构造函数的功能:将一个对象的非静态成员的值逐个复制给另一个对象,注意复制的是成员的值,这种复制方式也称为浅复制。因为静态成员属于整个类,而不属于某个对象,所以调用复制构造函数时静态成员不会受到影响。
  3.何时生成临时对象:情形1:按值传递对象注意是按值传递对象,按值传递意味着会创建一个原始对象的副本,
  情形2:函数返回对象时。
  情形3:用一个对象初始化另一个对象时即复制初始化,语句hyong x=y和hyong x=hyong(y)这里y是hyong类型的对象。都将调用复制构造函数,但有可能创建临时对象也有可能不创建临时对象而用复制构造函数直接初始化对象,这取决于编译器。
  4.临时对象是由复制构造函数创建的,当临时对象消失时会调用相应的析构函数。也就是说只要创建了临时对象就会多调用一次析构函数。
  5.何时使用复制构造函数:按值传递对象,函数返回对象,用一个对象初始化另一个对象即复制初始化时,根据元素初始化列表初始化数组元素。这四种情况都将调用复制构造函数。记住,复制构造函数只能用于初始化,不能用于赋值,赋值时不会调用复制构造函数,而是使用赋值操作符。
  6.直接初始化:直接初始化是把初始化式放在圆括号中的,对于类类型来说,直接初始化总是调用与实参匹配的构造函数来初始化的,
  7.复制初始化与复制构造函数:复制初始化使用=等于符号来初始化,复制初始化也是创建一个新对象,并且其初值来自于另一个已存在的对象,复制初始化总是调用复制构造函数来初始化的,复制初始化时首先使用指定的构造函数创建一个临时对象,然后用复制构造函数将临时对象的每个非static成员依次的复制到新创建的对象。复制构造函数执行的是逐个成员初始化。注意这里是用一个已存在的对象创建另一个新对象,与用构造函数直接创建一个新对象不一样,使用构造函数初始化时不会使用另一个对象。比如有类hyong,则语句hyong m(1,2)调用构造函数直接初始化,而语句hyong n=m则是用已存在的对象m去初始化一个新对象n,属于复制初始化。
  8.理解赋值与复制初始化的区别(重点):赋值是在两个已存在的对象间进行的,也就是用一个已存在的对象去改变另一个已存在对象的值。赋值将调用赋值操作符对对象进行操作,赋值操作符将在操作符重载中讲解。比如有类hyong,有语句hyong x(1);hyong y(1,2)则x=y;这就是赋值,因为对象x和y是已经存在的对象,而语句hyong x=y;则是复制初始化,是用一个已存在的对象y去创建一个新对象x,所以是复制初始化。
  9.复制初始化和赋值是在两个对象之间进行的操作,而直接初始化则不是。
  10.注意:使用复制构造函数不一定创建临时对象就如语句hyong x=hyong(y),其中y是hyong类型的对象,就有可能不创建临时对象,这取决于编译器。这里如果创建了临时对象则当临时对象消亡时将调用一次析构函数,而如果没有调用而是直接用复制构造函数初始化对象的就不会调用析构函数。
  11.复制构造函数的形式:hyong(const hyong & obj);它接受一个指向类对象的常量引用作为参数。定义为const是必须的,因为复制构造函数只是复制对象,所以没必要改变传递来的对象的值,声明为引用可以节省时间,如果是按值传递的话就会生成对象的副本,会浪费资源,而引用就不会。
  12.为什么需要定义自已的复制构造函数:如果类只包含类类型成员和内置类型的成员,则可以不用显示定义复制构造函数。但如果类中包含有指针或者有分配其他类型资源时就必须重新定义复制构造函数。因为类中有指针成员,当把用一个对象初始化另一个对象时,这时两个对象中的指针都指向同一段内存,这时如果其中一个对象被消毁了,这时对象中指针所指向的内存也同样被消毁,但另一个对象确不知道这种情况,这时就会出现问题。比如hyong类中含有一个成员指针p,当声明了hyong x=y其中y也是hyong类的对象,这时对象x和y中的指针成员p都指向同一段内存,而如果y被消毁,但x还没被消毁时就会出问题,这时y中对象的成员指针p已经释放了该内存资源,而x中的成员指针p还不知道已经释放了该资源,这时就会出问题。因为对象x和y中的成员指针共享同一段内存,所以对y中的成员指针p的修改就会影响到对象x中的成员指针。所有这些情况都需要重定义复制构造函数来显示的初始化成员的值,这种初始化方式也被称为深度复制。
  13.如果显示定义了复制构造函数则调用显示复制构造函数来直接初始化对象,如果没有显示定义复制构造函数,则调用默认的复制构造函数直接初始化对象。
  14.注意:1.在VC++中语句hyong n=m不生成临时对象,但如果显示定义了复制构造函数则调用显示复制构造函数来直接初始化对象n,如果没有显示定义复制构造函数,则调用默认的复制构造函数直接初始化对象n。
  2.在VC++中语句hyong m1=hyong(m)有可能生成临时对象也有可能不生成临时对象,如果显示定义了复制构造函数则用复制构造函数直接初始化对象m1,不生成临时对象。如果没有显示定义复制构造函数则复制构造函数将创造临时对象,初始化对象m1
  15.C++自动提供的成员函数,有:默认构造函数,复制构造函数,默认析构函数,赋值操作符,地址操作符即this指针,这五种函数如果用户没有定义,则系统会自动创建一个。
  16.直接调用类中的构造函数:可以在类中的函数,类外的独立函数,即main()函数中直接调用某一个类的构造函数,比如在main函数中可以有语句n=A(4);这里n是类A的对象,这里就是直接调用类A的构造函数创建一个类A的临时对象,然后把该临时对象的值赋给类A的对象n。在类中的函数和在类外的函数调用类的构造函数的方法和这里类似。注意语句n.A(4)是错误的语句,不能由对象调用类中的构造函数。
  例:复制构造函数的使用
  class hyong
  {
  public:
  hyong();
  hyong(int i);
  hyong(const hyong& obj);
  ~hyong();
  void h(hyong k);
  hyong f();
  int a,b,c;
  };
  hyong::hyong()
  {
  a=b=c=0;
  cout<<"gouchao"<<"\n";
  }
  hyong::hyong(int i)
  {
  a=b=c=i;
  cout<<"gouchao2"<<"\n";
  }
  hyong::~hyong()
  {
  cout<<"xigou"<<"\n";
  }
  //复制构造函数
  hyong::hyong(const hyong &obj)
  {
  a=obj.a;
  b=obj.b;
  c=obj.c;
  cout<<"fuzi"<<"\n";
  }
  //按值传递对象
  void hyong::h(hyong k)
  {
  cout<<"haoshu"<<k.a<<k.b<<"\n";
  }
  //反回对象。
  hyong hyong::f()
  {
  hyong m3(5);
  return m3;
  }
  //如果显示定义了复制构造函数则调用显示复制构造函数来直接初始化对象,如果没有显示定义复制构造函数,则调用默认的复制构造函数直接初始化对象。
  int main()
  {//以下为几种复制初始化的方式。
  hyong m(1);
  // hyong n=m和hyong m1=hyong(m)是否生成临时对象依编译器而定
  hyong n=m; //在VC++中此语句不生成临时对象,调用显示定义的复制构造函数初始化对象
  cout<<m.a<<m.b<<"\n";//
  cout<<n.a<<n.b<<"\n";//,输出和上句相同,调用显示定义的复制构造函数初始化对象n,而不会生成临时对象。
  hyong m1=hyong(m); //此语句要特别注意,因为此语句有可能生成临时对象也有可能不生成临时对象,如果显示定义了复制构造函数则用复制构造函数直接初始化对象m1,而不会生成临时对象。如果没有显示定义复制构造函数则复制构造函数将生成临时对象,然后对m1进行初始化。
  cout<<m1.a<<m1.b<<"\n"; //输出输出11,调用显示定义的复制构造函数初始化对象m1,不生成临时对象。如果没有定义复制构造函数则输出,同时会生成临时对象,临时对象撤消时会调用析构函数。
  hyong m2(m); cout<<m2.a<<m2.b<<"\n"; //输出11,直接调用复制构造函数,因此不会生成临时对象
  hyong *p=new hyong(m); cout<<p->a<<p->b<<"\n"; //不生成临时对象,直接调用复制构造函数初始化。
  //按值传递和返回对象的例子。
  h(m); cout<<"kkk"<<"\n"; //按值传递对象m,当调用函数h时就会使用复制控制函数生成一个临时对象,然后把这个临时对象复制给实参,当函数调用完毕时就会撤消临时对象,此时会调用一个析构函数,析构函数在h函数的作用域消失时才调用,也就是说在执行了h的函数体后才会调用析构函数。
  hyong m4=f(); cout<<m4.a<<m4.b<<"\n"; //输出55,用返回的对象初始化对象m4,此语句没有生成临时对象,原因还不清楚,待考证,可能与语句是复制初始化有关。
  hyong m5; m5=f(); //此语句调用函数f,f反回一个对象,在反回时会调用复制构造函数生成一个临时对象,并把这个临时对象作为默认赋值操作符的一个参数,因此这里不但调用了复制构造函数还调用了赋值操作符。
  cout<<m5.a<<m5.b<<"\n";
  hyong m6; m6=m; //把m的值赋给m6,注意这里不会调用复制构造函数,也不会生成临时对象,因为这里会把m当成是默赋值操作符的一个参数,调用的是默认赋值操作符。}
  例:直接调用类中的构造函数
  class A {public: int a; A(){a=0;} A(int i){a=i;} ~A(){cout<<"xi"<<"\n";}
  A f(){return A(3);} }; //在类中调用类的构造函数,当该函数被对象调用时反回由构造函数A构造的一个临时对象。
  A g() {return A(5);} //类外的函数调用类的构造函数的方法,注意,这里是直接使用函数名的。
  int main()
  { A m(1); A n(2); n=m.f(); cout<<n.a<<"\n"; //输出3,调用类中的f函数,f函数用构造函数反回一个临时对象。
  n=g(); cout<<n.a<<"\n"; //输出5,调用类外的函数g
  n=A(6); cout<<n.a; //在main函数中直接调用构造函数创造一个临时对象,然后把这个临时对象的值赋给对象n。
  //n.A(7); } //错误,不能用类的对象来调用构造函数。
分享到:
评论

相关推荐

    linux CC++ 码农有道教程-视频教程网盘链接提取码下载.txt

    《Linux C/C++ 一码农有道教程》是一门专为初学者设计的课程,通过系统性地讲解Linux操作系统和C/C++编程语言的基础知识和应用技巧,帮助学员快速掌握开发Linux应用程序的能力。课程包括理论与实践相结合的教学方式...

    《毕业设计》-一个码农的毕生所学!笔记 &amp; 教程 考研,就业,上学.语言篇,Android,C++,Java,Java

    一个码农的毕生所学!笔记 &amp; 教程。考研,就业,上学.语言篇,Android,C++,Java,JavaSc 一个码农的毕生所学!笔记 &amp; 教程。考研,就业,上学.语言篇,Android,C++,Java,JavaSc 一个码农的毕生所学!笔记 &amp; ...

    C++入门经典(第3版)+源代码

    Ivor Horton是世界著名的计算机...本书基本不需要读者具备任何C++知识,书中包含了理解C++的所有必要知识,读者可以从头开始编写自己的C++程序。本书也适合于具备另一种语言编程经验但希望全面掌握C++语言的读者。 ...

    王道C++长期班49期短期班最新课程.zip

    总的来说,王道C++长期班49期短期班最新课程.zip是为那些希望深化对C++语言理解、提升编程实战能力的学习者量身打造的一套完整教学资源。无论是编程新手还是已有一定基础的程序员,都能从这一课程中获得宝贵的学习...

    码农毕生所学!笔记 &amp; 教程 考研,就业,上学.语言篇,Android,C++,Java,JavaScript等

    一个码农的毕生所学!笔记 &amp; 教程。考研,就业,上学.语言篇,Android,C++,Java,JavaScript,Latex,MATLAB,NodeJS,PHP,Python,技术篇,docker,git,Linux,Maven,office,Spark,Spring,….zip一个码农的毕生所学!笔记 &...

    码农杂志第1期

    第一期的发布标志着这个平台为程序员提供了丰富的学习资源和交流空间。 在《码农》杂志第一期中,我们可以期待涵盖多个IT领域的精彩内容。首先,作为入门部分,可能会有对编程基础知识的回顾,帮助新手程序员巩固...

    C++构造解析json

    例如,创建一个键为"message",值为"Hello, World!"的对象: ```cpp root["message"] = "Hello, World!"; ``` - 数组可以通过`append`方法添加元素,例如: ```cpp Json::Value array; array.append("Element...

    吴文虎程序设计基础 课件 (c++)

    这套课件深入浅出地介绍了程序设计的基础概念,旨在帮助初学者掌握C++的核心知识,为后续的软件开发打下坚实的基础。 C++是一种强大的、面向对象的编程语言,广泛应用于系统软件、应用软件、游戏开发、设备驱动等...

    码农 杂志1-3期

    1. 编程语言:《码农》可能会深入探讨当前流行的编程语言,如Java、Python、C++、JavaScript等,包括它们的最新版本特性、应用场景、学习资源以及最佳实践。对于初学者,可能会有基础语法和进阶技巧的介绍;对于经验...

    码农第一期

    码农的草帽底下,是一颗充满创造力的自由不羁的头脑。 他们遵从最佳实践而痛恨陈规教条,他们欣赏天才而不迷信权威,他们喜欢思考而不轻易苟同。他们是技术人,却追求人文理想;他们敢于呐喊,说出自己的观点和...

    C语言调用C++类中的方法

    有时,我们可能需要在C语言项目中调用C++编写的类和方法,这种情况在跨语言交互或维护既有C代码库时尤为常见。本教程将详细讲解如何实现这一目标。 首先,为了使C语言能够调用C++的方法,我们需要确保C++类具备...

    码农杂志第3期

    图灵写给程序员的免费电子杂志《码农》,第三期,欢迎下载

    《码农》1-4期

    该文件包含了图灵社区出版的《码农》第一期到第四期的杂志。上面介绍了各种算法,访谈和IT行业的方方面面,致力于IT行业的可以看看。 码农的草帽底下,是一颗充满创造力的自由不羁的头脑。 他们遵从最佳实践而...

    Effective C++ 中文版第三版 高清PDF.pdf

    《Effective C++ 中文版第三版》是一本针对C++编程语言的学习者和开发者,提供了大量实践建议和最佳实践的手册。本书由Scott Meyers编写,他是C++领域内知名的作家和技术讲师。这本书旨在帮助读者编写更安全、更高效...

    码农杂志第6期

    《码农》杂志是图灵出版社会面向程序员推出的一份免费电子杂志,旨在为编程爱好者和从业人员提供最新的技术资讯、深度分析以及实用的编程技巧。第六期的发布,无疑为广大的码农群体带来了丰富的知识盛宴。以下是这期...

    精品--C++从零开始深度学习.zip

    【C++从零开始深度学习】是一门针对初学者精心设计的课程,旨在帮助学习者逐步掌握C++编程语言,并以此为基础深入理解深度学习的基本原理和实现方法。C++是一种强大的、通用的编程语言,以其高效性和灵活性在科学...

    VS2015 C# 调用C++Dll 附C++源文件

    你可以将DLL复制到C#项目的输出目录(通常是`bin\Debug`或`bin\Release`),或者在项目的“属性”-&gt;“调试”选项卡中设置“工作目录”为DLL的路径。 5. **运行C#项目** - 编译并运行C#程序,你应该能看到C#调用C++...

Global site tag (gtag.js) - Google Analytics