复制构造函数
形如className :: className(const &)   /   className :: className(const className &)后者能以常量对象作为参数
如不写复制构造函数,则编译器默认提供,为了完成对象的复制功能

它起作用有三个工作环境:

1.一个对象初始化另一个同类的对象

  1. Simple c2(c1);
  2. Simple c2 = c1;//初始化

2.如果某函数有一个参数是类的一个对象,那么该函数被调用时,类的复制构造函数被调用

  1. Simple A
  2. {
  3. pbulic:
  4. A(){};
  5. A(A & a)
  6. {
  7. cout<<.....<<endl;
  8. }
  9. };
  10. void Fun(A a1){}
  11. int main()
  12. {
  13. A a;
  14. Fun(a);//.....
  15. return ;
  16. }

3.如果函数的返回值是类的对象时,则函数返回是,类的复制构造函数被调用

  1. class Simple
  2. {
  3. pbulic:
  4. int x;
  5. Simple(int n){x = n;};
  6. Simple(const Simple & a)
  7. {
  8. x = a.x;
  9. cout<<"Copy constructor called"<<endl;
  10. }
  11. };
  12. Simple Fun()
  13. {
  14. Simple b();
  15. return b;//作为复制构造函数的参数
  16. }
  17. int main()
  18. {
  19. cout<<Fun().x<<endl;// Copy constructor called 100
  20. return ;
  21. }

注意:对象间的赋值不导致复制构造函数的调用

A c1,c2;
c2 = c1 ;//不会调用
A C3(C1);//这是初始化操作,会调用赋值构造函数

在函数参数列表中,为节省开销,不引发复制构造函数的调用,使用ClassName & 引用类型为参数,
又为了确保实参值不变,再在引用前加上const关键字。复制构造函数往往加const和&,具体可以点这里


类型转换构造函数

它的目的是实现类型的自动转换,并且只有一个参数。当需要的时候,编译系统会自动调用转换构造函数,建立

一个无名的临时对象(或临时变量)。

  1. class Complex
  2. {
  3. public:
  4. double real, imag;
  5. Complex( int i)
  6. {//类型转换构造函数
  7. cout << "IntConstructor called" << endl;
  8. real = i; imag = ;
  9. }
  10. Complex(double r,double i) {real = r; imag = i; }
  11. };
  12. int main ()
  13. {
  14. Complex c1(,);
  15. Complex c2 = ;
  16. c1 = ; // 9被自动转换成一个临时Complex对象
  17. cout << c1.real << "," << c1.imag << endl;
  18. return ;
  19. }
  1. class Complex
  2. {
  3. public:
  4. double real, imag;
  5. explicit Complex( int i)
  6. {//显式类型转换构造函数
  7. cout << "IntConstructor called" << endl;
  8. real = i; imag = ;
  9. }
  10. Complex(double r,double i) {real = r; imag = i; }
  11. };
  12. int main ()
  13. {
  14. Complex c1(,);
  15. Complex c2 = Complex();
  16. c1 = ; // error, 9不能被自动转换成一个临时Complex对象
  17. c1 = Complex() //ok
  18. cout << c1.real << "," << c1.imag << endl;
  19. return ;
  20. }

析构函数:~类名(){}

它没有返回值和参数,一个类对应一个析构函数,在类的对象消亡时自动调用,也可以手动调用进行对象消亡的善后工作。如果懒的去写,编译器自动会生成缺省析构函数,但是什么也不做,如果写了,就不自动生成了。

  1. class Simple
  2. {
  3. private :
  4. char * p;
  5. public:
  6. Simple()
  7. {
  8. p = new char[];
  9. }
  10. ~ Simple () ;
  11. };
  12. Simple ::~ Simple()
  13. {
  14. delete [] p;
  15. }

在对一个对象进行delete时,调用一次析构函数,在delete[]对象数组时,会调用n次析构函数,取决于数组大小。此外:

  1. class CMyclass
  2. {
  3. public:
  4. ~CMyclass() { cout << "destructor" << endl; }
  5. };
  6. CMyclass obj;
  7. CMyclass fun(CMyclass sobj )
  8. { //参数对象消亡也会导致析
  9. //构函数被调用
  10. return sobj; //函数调用返回时生成临时对象返回
  11. }
  12. int main()
  13. {
  14. obj = fun(obj); //函数调用的返回值(临时对象)被
  15. return ; //用过后,该临时对象析构函数被调用
  16. }
  17. //destructor形参对象消亡
  18. //destructor临时对象消亡
  19. //destructor全局对象消亡

new出来的对象或对象数组,不delete就不会消亡,就不会调用析构函数!!不是new出来的,则在生命期结束会自动调用


关于引用:引用是C++有的,C所没有的,标志为 &,即C的取地址符。它的声明为这样

  1. int n = ;
  2. int & r = n; //r为 int & 类型

其中r和n指向同一片地址空间 ,对 r和n的修改都会改变原来是4的那个值,相当于为n取了个别名r

在定义引用时一定要将其初始化成引用某个变量。并且之后不会引用别的变量
只能引用变量,不能引用常量和表达式

一个简单而又形象的,见得次数很多的例子:交换元素

  1. void swap( int * a, int * b)
  2. {
  3. int tmp;
  4. tmp = * a;
  5. * a = * b;
  6. * b = tmp;
  7. }
  8. int n1, n2;
  9. swap(& n1,& n2) ; // n1,n2的值被交换
  1. //用了引用
  2. void swap( int & a, int & b)
  3. {
  4. int tmp;
  5. tmp = a;
  6. a = b;
  7. b = tmp;
  8. }
  9. int n1, n2;
  10. swap(n1,n2) ; // n1,n2的值被交换
  1. //en ..交换还可以这样写,当然远不如swap(a,b)写的快哈
  2. int a = ;
  3. int b = ;
  4. a = a + b;
  5. b = a - b;
  6. a = a - b;
  7. cout<<a<<" "<<b<<endl;
  8. a = a ^ b;
  9. b = a ^ b;
  10. a = a ^ b;
  11. cout<<a<<" "<<b<<endl;

引用还可以作为函数的返回值

  1. int n = ;
  2. int & SetValue()
  3. {
  4. return n;
  5. }
  6. int main()
  7. {
  8. SetValue() = ;
  9. cout << n;return ;
  10. } //输出: 40

关于常引用

int n;
const int & r = n;
r = 10;//error 不能通过常引用r改变n的值
n = 30;//n的值可以变化
const T & 和T & 是不同的类型!!!
T & 类型的引用T类型的变量可以用来初始化const T & 类型的引用
int n = 8;
int & r1 = n;
const int r2 = r1;//初始化const T & 类型的引用。
const T 类型的常变量和const T & 类型的引用则不能用来初始化T &类型的引用,
除非进行强制类型转换


常量指针

  1. //1.
  2. int n,m
  3. const int * p = n;//常量指针
  4. *p = //error 不可以通过修改常量指针修改指向的内容
  5. n = ;//ok
  6. p = & m;//ok 常量指针可以指向别的内容
  7.  
  8. //2.不可以把常量指针赋值给非常量指针(强转可以),反之可以
  9. const int * p;
  10. int * p2;
  11. p1 = p2; //ok
  12. p2 = p1; //error
  13. p2 = (int * ) p1; //ok,强制类型转换

指针常量

  1. int a,b;
  2. int const *p = & a;
  3. * p = ;//通过指针修改所指向的内容,ok
  4. p = & b;//error 不可更改所指向的地址

这两个不要搞混淆了。。。。

简单的记忆,抓住第一个是常量在前,就意味着整个后面的地址内容是个常量,不可以通过指针去修改它,但是指向谁是可以变的;指针常量,这个常量在指针后面,表明这个指针所指向的地址不能变了,但你可以用它修改地址所对应的内容。。


动态内存分配:

变量: int * px = new int; //大小为sizeof(int)
数组: int * pn = new int[20];
释放动态分配的内存:
int * px = new int;
delete px;//只能删除一次
//数组
int * pn = new int[20];
delete [] pn;

C++复制构造函数,类型转换构造函数,析构函数,引用,指针常量和常量指针的更多相关文章

  1. C++类构造函数、拷贝构造函数、复制构造函数、复制构造函数、构造函数显示调用和隐式调用

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

  2. C++11新特性之0——移动语义、移动构造函数和右值引用

    C++引用现在分为左值引用(能取得其地址)和 右值引用(不能取得其地址).其实很好理解,左值引用中的左值一般指的是出现在等号左边的值(带名称的变量,带*号的指针等一类的数据),程序能对这样的左值进行引 ...

  3. 《挑战30天C++入门极限》C++类对象的复制-拷贝构造函数

        C++类对象的复制-拷贝构造函数 在学习这一章内容前我们已经学习过了类的构造函数和析构函数的相关知识,对于普通类型的对象来说,他们之间的复制是很简单的,例如: int a = 10; int ...

  4. 构造函数constructor 与析构函数destructor(五)

    我们知道当调用默认拷贝构造函数时,一个对象对另一个对象初始化时,这时的赋值时逐成员赋值.这就是浅拷贝,当成员变量有指针时,浅拷贝就会在析构函数那里出现问题.例如下面的例子: //test.h #ifn ...

  5. 类型转换构造函数 及使用explicit避免类型自动转换------新标准c++程序设计

    类型转换构造函数:  除复制构造函数外,只有一个参数的构造函数一般可以称作类型转换构造函数,因为这样的构造函数能起到类型自动转换的作用.例如下面的程序: #include<iostream> ...

  6. C++转换构造函数与类型转换构造函数

    转换构造函数: 转换构造函数的只有一个形参: Student(float s) { score = s; age = ; } 如果已经在上面定义了构造函数: Student(); //建立对象c1,由 ...

  7. 构造函数constructor 与析构函数destructor(二)

    (1)转换构造函数 转换构造函数的定义:转换构造函数就是把普通的内置类型转换成类类型的构造函数,这种构造函数只有一个参数.只含有一个参数的构造函数,可以作为两种构造函数,一种是普通构造函数用于初始化对 ...

  8. python中的构造函数和构造函数和析构函数的作用

    构造函数和构造函数和析构函数都属于python中的特殊方法 其中的“__del__”就是一个析构函数了,当使用del 删除对象时,会调用他本身的析构函数,另外当对象在某个作用域中调用完毕,在跳出其作用 ...

  9. C++ 引用计数技术及智能指针的简单实现

    一直以来都对智能指针一知半解,看C++Primer中也讲的不够清晰明白(大概是我功力不够吧).最近花了点时间认真看了智能指针,特地来写这篇文章. 1.智能指针是什么 简单来说,智能指针是一个类,它对普 ...

随机推荐

  1. colock

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  2. Selenium踩坑记之iFrame的定位与切换

    转自:https://www.jianshu.com/p/6e7d0359e4bb Selenium是浏览器自动化测试的工具之一,用过的人都懂他的好,也被他坑的不要不要的.今天就聊聊Selenium的 ...

  3. py文件单独调试django ORM的配置

    1.新建一个py文件 2.代码环境搭建 import os if __name__ != '__main__': exit() # 加载django项目的配置信息 os.environ.setdefa ...

  4. 使用Scanner

    在上个步骤中,每次要发不同的数据都需要修改代码 可以使用Scanner读取控制台的输入,并发送到服务端,这样每次都可以发送不同的数据了.   1 2 3 4 5 6 7 8 9 10 11 12 13 ...

  5. php 微信公众平台OAuth2.0网页授权,获取用户信息代码类封装demo

    get_wx_data.php <?php /** * 获取微信用户信息 * @author: Lucky hypo */ class GetWxData{ private $appid = ' ...

  6. Java Sound Capture from Microphone working code

    转载自:http://ganeshtiwaridotcomdotnp.blogspot.com/2011/12/java-sound-capture-from-microphone.html Soun ...

  7. Vue cli4.0 代理配置

    proxy: { '/service': { target: 'http://192.168.40.243:3000/', //对应自己的接口 changeOrigin: true, ws: true ...

  8. (一)IDEA修改HTML不生效(未热部署)

    一.问题 IDEA 版本:2018.1.2 项目类型:SpringBoot 描述 : 修改JSP文件内容时,不会热部署,需要每次都重启项目才生效. 二.解决方案 加入Springboot开发者工具,即 ...

  9. ubuntu18.04安装golang

    首先我们通过如下命令安装golang: sudo add-apt-repository ppa:longsleep/golang-backports sudo apt-get update sudo ...

  10. JSON和JSONP具体是干神马的呢? (含jQuery实例)

    说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求如何解决?这两个问题目前都有不同的解决方案,比如数据可以用自定义字符串或者用XML来描述,跨域可以通过服 ...