zoukankan      html  css  js  c++  java
  • C++复制构造函数,类型转换构造函数,析构函数,引用,指针常量和常量指针

    复制构造函数
    形如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 0;
    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(100);
    15     return b;//作为复制构造函数的参数
    16 }
    17 int main()
    18 {
    19     cout<<Fun().x<<endl;// Copy constructor called 100
    20     return 0;
    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 = 0; 
     9     }
    10     Complex(double r,double i) {real = r; imag = i; }
    11 };
    12 int main ()
    13 {
    14     Complex c1(7,8);
    15     Complex c2 = 12;
    16     c1 = 9; // 9被自动转换成一个临时Complex对象
    17     cout << c1.real << "," << c1.imag << endl;
    18     return 0;
    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 = 0; 
     9     }
    10     Complex(double r,double i) {real = r; imag = i; }
    11 };
    12 int main () 
    13 {
    14     Complex c1(7,8);
    15     Complex c2 = Complex(12);
    16     c1 = 9; // error, 9不能被自动转换成一个临时Complex对象
    17     c1 = Complex(9) //ok
    18     cout << c1.real << "," << c1.imag << endl;
    19     return 0;
    20 }

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

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

     1 class Simple
     2 {
     3 private :
     4     char * p;
     5 public:
     6     Simple()
     7     {
     8         p = new char[10];
     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 0; //用过后,该临时对象析构函数被调用
    16 }
    17 //destructor形参对象消亡
    18 //destructor临时对象消亡
    19 //destructor全局对象消亡

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


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

    1 int n = 4; 
    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;
     3     int b = 5;
     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 = 4;
     2 int & SetValue() 
     3 { 
     4     return n; 
     5 }
     6 int main() 
     7 {
     8     SetValue() = 40;
     9     cout << n;return 0;
    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 = 5//error  不可以通过修改常量指针修改指向的内容
     5 n = 5;//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 = 9;//通过指针修改所指向的内容,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;

  • 相关阅读:
    洛谷P2050 美食节
    洛谷P2150 寿司晚宴
    区间最深LCA
    三层交换机
    VLAN 及 GVRP 配置
    GVRP
    VLAN IEEE802.1Q
    以太网端口技术
    网关与路由器
    Quidway S系列交换机
  • 原文地址:https://www.cnblogs.com/ygsworld/p/11260824.html
Copyright © 2011-2022 走看看