转载:https://www.cnblogs.com/raichen/p/4752025.html

构造函数是干什么的

该类对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数,由构造函数完成成员的初始化工作。

故:构造函数的作用:初始化对象的数据成员。

构造函数的种类

class Complex
{         private :double m_real;double m_imag;public:// 无参数构造函数// 如果创建一个类你没有写任何构造函数,则系统会自动生成默认的无参构造函数,函数为空,什么都不做// 只要你写了一个下面的某一种构造函数,系统就不会再自动生成这样一个默认的构造函数,如果希望有一个这样的无参构造函数,则需要自己显示地写出来Complex(void){m_real = 0.0;m_imag = 0.0;} // 一般构造函数(也称重载构造函数)// 一般构造函数可以有各种参数形式,一个类可以有多个一般构造函数,前提是参数的个数或者类型不同(基于c++的重载函数原理)// 例如:你还可以写一个 Complex( int num)的构造函数出来// 创建对象时根据传入的参数不同调用不同的构造函数Complex(double real, double imag){m_real = real;m_imag = imag;         }// 复制构造函数(也称为拷贝构造函数)// 复制构造函数参数为类对象本身的引用,用于根据一个已存在的对象复制出一个新的该类的对象,一般在函数中会将已存在对象的数据成员的值复制一份到新创建的对象中// 若没有显示的写复制构造函数,则系统会默认创建一个复制构造函数,但当类中有指针成员时,由系统默认创建该复制构造函数会存在风险,具体原因请查询有关 “浅拷贝” 、“深拷贝”的文章论述Complex(const Complex & c){// 将对象c中的数据成员值复制过来m_real = c.m_real;m_img  = c.m_img;}            // 类型转换构造函数,根据一个指定的类型的对象创建一个本类的对象// 例如:下面将根据一个double类型的对象创建了一个Complex对象Complex::Complex(double r){m_real = r;m_imag = 0.0;}// 等号运算符重载// 注意,这个类似复制构造函数,将=右边的本类对象的值复制给等号左边的对象,它不属于构造函数,等号左右两边的对象必须已经被创建// 若没有显示的写=运算符重载,则系统也会创建一个默认的=运算符重载,只做一些基本的拷贝工作Complex &operator=(const Complex &rhs){// 首先检测等号右边的是否就是左边的对象本,若是本对象本身,则直接返回if ( this == &rhs ) {return *this;}// 复制等号右边的成员到左边的对象中this->m_real = rhs.m_real;this->m_imag = rhs.m_imag;// 把等号左边的对象再次传出// 目的是为了支持连等 eg:    a=b=c 系统首先运行 b=c// 然后运行 a= ( b=c的返回值,这里应该是复制c值后的b对象)    return *this;}
};

下面使用上面定义的类对象来说明各个构造函数的用法:

void main()
{// 调用了无参构造函数,数据成员初值被赋为0.0Complex c1,c2;// 调用一般构造函数,数据成员初值被赋为指定值Complex c3(1.0,2.5);// 也可以使用下面的形式Complex c3 = Complex(1.0,2.5);// 把c3的数据成员的值赋值给c1// 由于c1已经事先被创建,故此处不会调用任何构造函数// 只会调用 = 号运算符重载函数c1 = c3;// 调用类型转换构造函数// 系统首先调用类型转换构造函数,将5.2创建为一个本类的临时对象,然后调用等号运算符重载,将该临时对象赋值给c1c2 = 5.2;// 调用拷贝构造函数( 有下面两种调用方式) Complex c5(c2);Complex c4 = c2;  // 注意和 = 运算符重载区分,这里等号左边的对象不是事先已经创建,故需要调用拷贝构造函数,参数为c2       }

参考:http://www.cnblogs.com/xkfz007/archive/2012/05/11/2496447.html

复制构造函数

几个原则:

C++ primer p406 :复制构造函数是一种特殊的构造函数,具有单个形参,该形参(常用const修饰)是对该类类型的引用。当定义一个新对象并用一个同类型的对象对它进行初始化时,将显示使用复制构造函数。当该类型的对象传递给函数或从函数返回该类型的对象时,将隐式调用复制构造函数。

C++支持两种初始化形式:复制初始化(int a = 5;)和直接初始化(int a(5);)对于其他类型没有什么区别,对于类类型直接初始化直接调用实参匹配的构造函数,复制初始化总是调用复制构造函数,也就是说:

A x(2);  //直接初始化,调用构造函数
A y = x;  //复制初始化,调用复制构造函数

必须定义复制构造函数的情况:

只包含类类型成员或内置类型(但不是指针类型)成员的类,无须显式地定义复制构造函数也可以复制;

有的类有一个数据成员是指针,或者是有成员表示在构造函数中分配的其他资源,这两种情况下都必须定义复制构造函数。

什么情况使用复制构造函数:

类的对象需要拷贝时,拷贝构造函数将会被调用。以下情况都会调用拷贝构造函数:
(1)一个对象以值传递的方式传入函数体 
(2)一个对象以值传递的方式从函数返回 
(3)一个对象需要通过另外一个对象进行初始化。

深拷贝和浅拷贝:

所谓浅拷贝,指的是在对象复制时,只对对象中的数据成员进行简单的赋值,默认拷贝构造函数执行的也是浅拷贝。在“深拷贝”的情况下,对于对象中动态成员,就不能仅仅简单地赋值了,而应该重新动态分配空间

如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝

上面提到,如果没有自定义复制构造函数,则系统会创建默认的复制构造函数,但系统创建的默认复制构造函数只会执行“浅拷贝”,即将被拷贝对象的数据成员的值一一赋值给新创建的对象,若该类的数据成员中有指针成员,则会使得新的对象的指针所指向的地址与被拷贝对象的指针所指向的地址相同,delete该指针时则会导致两次重复delete而出错。下面是示例:

#include <iostream.h>
#include <string.h>
class Person
{
public :// 构造函数Person(char * pN){cout << "一般构造函数被调用 !\n";m_pName = new char[strlen(pN) + 1];//在堆中开辟一个内存块存放pN所指的字符串if(m_pName != NULL) {//如果m_pName不是空指针,则把形参指针pN所指的字符串复制给它strcpy(m_pName ,pN);}}        // 系统创建的默认复制构造函数,只做位模式拷贝Person(Person & p)    { //使两个字符串指针指向同一地址位置         m_pName = p.m_pName;         }~Person( ){delete m_pName;}private :char * m_pName;
};void main( )
{ Person man("lujun");Person woman(man); // 结果导致   man 和    woman 的指针都指向了同一个地址// 函数结束析构时// 同一个地址被delete两次
}// 下面自己设计复制构造函数,实现“深拷贝”,即不让指针指向同一地址,而是重新申请一块内存给新的对象的指针数据成员
Person(Person & chs);
{// 用运算符new为新对象的指针数据成员分配空间m_pName=new char[strlen(p.m_pName)+ 1];if(m_pName)         {// 复制内容strcpy(m_pName ,chs.m_pName);}// 则新创建的对象的m_pName与原对象chs的m_pName不再指向同一地址了
}

重载赋值操作符:

通过定义operate=的函数,可以对赋值进行定义。像其他任何函数一样,操作符函数有一个返回值和形参表。形参表必须具有与该操作符操作数书目相同的形参(如果操作符是一个成员,则包括隐式this形参)。赋值是二元运算,所以该操作符函数有两个形参:第一个形参(隐含的this指针)对应着左操作数,第二个形参对应右操作数。

一个应用了对赋值号重载的拷贝构造函数的例子:

#include <iostream>using namespace std;class A
{
public:A(int);//构造函数A(const A &);//拷贝构造函数~A();void print();int *point;A &operator=(const A &);
};A::A(int p)
{point = new int;*point = p;
}A::A(const A &b)
{*this = b;cout<<"调用拷贝构造函数"<<endl;
}A::~A()
{delete point;
}void A::print()
{cout<<"Address:"<<point<<" value:"<<*point<<endl;
}A &A::operator=(const A &b)
{if( this != &b){delete point;point = new int;*point = *b.point;}
}int main()
{A x(2);A y = x;x.print();delete x.point;y.print();return 0;
}

参见:C++拷贝构造函数详解:http://blog.csdn.net/lwbeyond/article/details/6202256

C++构造函数详解(复制构造函数)相关推荐

  1. java的构造函数详解,Java构造函数与普通函数用法详解

    函数也被称为方法! 函数的作用及特点: 1.用于定义功能,将功能封装. 2.可以提高代码的复用性. 函数注意事项: 1.不能进行函数套用(不可以在函数内定义函数). 2.函数只有被调用才能被执行. 3 ...

  2. c++类的构造函数详解

    c++构造函数的知识在各种c++教材上已有介绍,不过初学者往往不太注意观察和总结其中各种构造函数的特点和用法,故在此我根据自己的c++编程经验总结了一下c++中各种构造函数的特点,并附上例子,希望对初 ...

  3. [转]c++类的构造函数详解

    c++构造函数的知识在各种c++教材上已有介绍,不过初学者往往不太注意观察和总结其中各种构造函数的特点和用法,故在此我根据自己的c++编程经验总结了一下c++中各种构造函数的特点,并附上例子,希望对初 ...

  4. c++构造函数详解(转)

    c++构造函数的知识在各种c++教材上已有介绍,不过初学者往往不太注意观察和总结其中各种构造函数的特点和用法,故在此我根据自己的c++编程经验总结了一下c++中各种构造函数的特点,并附上例子,希望对初 ...

  5. 构造函数详解_const的部分分析,部分转载于http://ticktick.blog.51cto.com/823160/194307

    c++构造函数的知识在各种c++教材上已有介绍,不过初学者往往不太注意观察和总结其中各种构造函数的特点和用法,故在此我根据自己的c++编程经验总结了一下c++中各种构造函数的特点,并附上例子,希望对初 ...

  6. C++构造函数详解及显示调用构造函数

    c++类的构造函数详解 一. 构造函数是干什么的 class Counter { public:          // 类Counter的构造函数          // 特点:以类名作为函数名,无 ...

  7. c++ 构造函数详解

    c++ 构造函数详解 构造函数是干什么的 构造函数的分类 拷贝构造函数 浅拷贝与深拷贝 c++ 构造函数详解 构造函数是干什么的 该类对象被创建的时候,编译系统对象分配内存空间,并自动调用该构造函数, ...

  8. webSocket(与http请求区别、请求和返回示例、替代方法:ajax轮询、long poll、Flash、NodeJS实现WebSocket通信代码、原理、WebSocket构造函数详解)

    目录 简介 优点 请求示例 请求成功返回示例 替代方法 Ajax 轮询 long poll Flash NodeJS实现webSocket(ws模块) 服务端代码 客户端代码 在线网页客户端 运行结果 ...

  9. 知识:JavaScript构造函数详解

    构造函数详解 铺垫:面向对象编程 一.构造函数是什么? 二.构造函数的作用? 三.构造函数的执行过程? 四.构造函数的返回值? 五.构造函数为什么要用new关键字调用? 六.构造函数的实例成员和静态成 ...

  10. C++——拷贝构造函数详解

    C++--拷贝构造函数详解 1.拷贝构造函数的特点: 2.通过例子引入拷贝构造: 3构造对象的时候使用引用返回与不使用引用返回的问题: 3.1不使用引用返回: 3.2引用返回--从已经死亡的地址接收值 ...

最新文章

  1. MSSQL-最佳实践-行级别安全解决方案
  2. 如何使用Putty登录安装在VirtualBox里的ubuntu
  3. 用位运算计算两数的和
  4. w3c的ajax操作函数,关于ajax的使用方法_例题、ajax的数据处理
  5. 心生想往 ... ...
  6. MS CRM 2011 RC中的新特性(9)—全新的工作流 脚本设计模式
  7. 【AI视野·今日NLP 自然语言处理论文速览 第二十六期】Wed, 3 Nov 2021
  8. 研发工程师如何转型项目经理
  9. 从第一范式(2nf)到第二范式(3nf)_啥是数据库范式
  10. pymssql 安装后只有 .disk-info_龙虎榜之防盗扣安装榜主—王兰香
  11. 如何格式化电脑_如何将c盘格式化,垃圾文件太多,不知道怎么办
  12. Java实现密码学工具,集成了对称加密算法DES,AES,IDEA,公开加密算法RSA,ECC,散列算法MD5,SHA1,CRC32,以及RSA,DSA,ECDSA数字签名验证示例。
  13. 【实战】颠覆银行基础架构的区块链
  14. .NET WebAPI 用ExceptionFilterAttribute实现错误(异常)日志的记录(log4net做写库操作)...
  15. 2018中国云原生用户大会:网易云深度解析微服务框架
  16. 试简述smtp通信的三个阶段的过程_POP3_SMTP_IMAP初步介绍
  17. python中eof怎么改正_如何修复Python3中读取用户输入时的EOF错误?
  18. VSFTPD 上传文件 200 227 553错误
  19. 解决ueditor上传图片报Nginx 502 bad gateway问题
  20. 2022SWJTUACM新秀杯题解

热门文章

  1. 跨域 No 'Access-Control-Allow-Origin' header is present on the requested resource
  2. asp.net页面生命周期之页面的终结阶段
  3. poj 1141 Brackets Sequence(线性dp)
  4. 常见makefile写法
  5. 虚拟机vmware硬盘扩容方法
  6. Hibernate插入、查询、删除操作 HQL (转)
  7. Beta冲刺Day4
  8. 编译hadoop,spark遇到的问题总结
  9. 阅兵奇葩服装:美军顶鸡毛掸子 伊军扮鬼妖
  10. 开始我的.NET的学习旅程