精华内容
下载资源
问答
  • C++11六大函数(构造函数,移动构造函数,移动赋值操作符,复制构造函数,赋值操作符,析构函数) 在C++中,有三大函数复制控制(复制构造函数,赋值操作符,析构函数),而在C++11中,加入了移动...

    C++11六大函数(构造函数,移动构造函数,移动赋值操作符,复制构造函数,赋值操作符,析构函数)

    在C++中,有三大函数复制控制(复制构造函数,赋值操作符,析构函数),而在C++11中,加入了移动构造函数,移动赋值操作符。我就斗胆将他们命名为六大函数好了。

    一、构造函数

    c++primer中说过:构造函数是特殊的成员函数,只要创建类类型的新对象,都要执行构造函数。构造函数的工作就是保证每个对象的数据成员具有合适的初始值。

    构造函数与其他函数不同:构造函数和类同名,没有返回类型。

    构造函数与其他函数相同:构造函数也有形参表(可为void)和函数体。  (参数表为void的构造函数为默认构造函数)

    构造函数构造类对象的顺序是:1.内存分配,构造函数调用的时候 隐士\显示的初始化各数据。

    2.执行构造函数的运行。

    1、构造函数初始化表

    1. A() :a(0){}  

    我们使用构造函数初始化表示初始化数据成员,然而在没有使用初始化表的构造函数则在构造函数体中对数据成员赋值。

    在我们编写类的时候,有些成员必须在构造函数初始化表中进行初始化。(没有默认构造函数的类类型成员,const或者引用类型成员)

    在编写代码的时候,要注意的是:可以初始化const对象或者引用类型的对象,但不能对他们进行赋值。 也就是需要在我们执行构造函数函数体之前完成初始化工作,所以唯一的机会就是初始化表。从这一点可以看出初始化表的执行先于函数体。

    在初始化表中,成员被初始化的次序不是你编写初始化表的次序,而是定义成员的次序。

     

    初始化列表在初始化类类型的成员时,要指定实参并传递给成员类型的一个构造函数。

    在c++primer中有一个书店的例子:

    1. Sales-item(): isbn(10, '9'), units_sold(0), revenue(0.0) {}  

     

    我们的初始化表在什么时候必须使用呢 ?

    当有一个类成员,他本身就是结构或者类的时候,并且只有一个带参数的构造函数,(无默认构造函数) 此时我们要对成员进行初始化,就需要调用成员的构造函数,此时需要我们的初始化表,如果不使用初始化表,那么内存分配就会出问题。

    初始化列表的优点:主要是对于自定义类型,初始化列表是作用在函数体之前,他调用构造函数对对象进行初始化。

    然而在函数体内,需要先调用构造函数,然后进行赋值,这样效率就不如初始化表。

     

     

    2、默认实参构造函数

    1. A(int i = 1) :a(i), ca(i), ra(i){}  

     

    3、默认构造函数

    合成的默认构造函数:当类中没有定义构造函数(注意是构造函数)的时候,编译器自动生成的函数。

    但是我们不能过分依赖编译器,如果我们的类中有复合类型或者自定义类型成员,我们需要自己定义构造函数。

    自定义的默认构造函数:

    1. A(): a(0) {}  
    2. A(int i = 1): a(i) {}  

    可能疑问的是第二个构造函数也是默认构造函数么?是的,因为参数中带有默认值。

    我们来看一张图,就会一目了然了:

     

    4、类型转换

    在C++primer中,书店问题中的一个例子是 传递string对象或者iostream对象到参数中,会发生隐式转换,这样就会出现问题。

    explicit关键字可以抑制隐式转换。

    1. explicit Sales_item(const string &book): isbn(book) {}  


    如果我们声明了构造函数禁止隐式转换, 可以将其他对象显示转换后传入构造函数。

    1. string a = "d";  
    2. item.same(Sales_item(a));  


    二、移动构造函数

    在C++11中新加入的特性!

    在上一篇blog中我加入了一张图,可以具体看到移动构造函数的运行原理。

    此时,我们偷走了临时变量的内存空间,据为己用。节省了开辟空间的时间。

    1. A(A && h) : a(h.a)  
    2. {  
    3.     h.a = nullptr; //还记得nullptr?  
    4. }  


    可以看到,这个构造函数的参数不同,有两个&操作符,   移动构造函数接收的是“右值引用”的参数。

    还要来说一下,这里h.a置为空,如果不这样做,h.a在移动构造函数结束时候执行析构函数会将我们偷来的内存析构掉。h.a会变成悬垂指针

    移动构造函数何时触发?  那就是临时对象(右值)。用到临时对象的时候就会执行移动语义。

    这里要注意的是,异常发生的情况,要尽量保证移动构造函数 不发生异常,可以通过noexcept关键字,这里可以保证移动构造函数中抛出来的异常会直接调用terminate终止程序。

    右值引用:

    在上一篇blog中,我们提到过将亡值,他是c++11新增的跟右值引用相关的表达式。

    在c++11中,右值引用就是对一个右值进行引用的类型,右值通常不具有名字,我们就只能通过引用的方式找到它的存在了。

    比较一下下面两条语句:

    1. T &&a = returna();  
    2. T b = returnb();  

    此时a是右值引用,他比b少了一次对象析构和对象构造的过程。a直接绑定了returna返回的临时变量。b只是由临时变量值构造而成的。

    应该可以看清楚了吧。右值引用就是让返回的右值(临时对象)重获新生,延长生命周期。临时对象析构了,但是右值引用存活。

    不过要注意的是,右值引用不能绑定左值:int a; int &&c = a;   这样是不行的。


    这里有一个函数就是 move函数,它能够将左值强制转换成右值引用。

     

    三、移动赋值操作符

    他的原理跟移动构造函数相同,这里不再多说。

    给出实现代码:

    1. A & operator = (A&& h)  
    2. {  
    3.     assert(this != &h);  
    4.   
    5.     a = nullptr;  
    6.     a = move(h.a);  
    7.     h.a = nullptr;  
    8.     return *this;  
    9. }  



     

    复制控制

    四、复制构造函数

    他是一种特殊的构造函数,具有单个形参,形参是对该类类型的引用。当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式使用复制构造函数。当将该类型的对象传递给函数或从函数返回该类型的对象时,将隐式使用复制构造函数。

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

    1.、类有一个或者多个数据成员是指针。

    2、有成员表示在构造函数中分配的其他资源。另外的类在创建新对象时必须做一些特定的工作。

    下面给出赋值构造函数的编写:

    1. A(const A& h) :a(h.a){}  

    如果不想让对象复制呢? 那就将复制构造函数声明为:private;

    五、赋值操作符

    他跟构造函数一样,赋值操作符可以通过制定不同类型的右操作数而重载。

    赋值和复制经常是一起使用的,这个要注意。

    下面给出赋值操作符的写法:

    1. A& operator = (const A& h)  
    2. {  
    3.     assert(this != &h);  
    4.   
    5.     this->a = h.a;  
    6.   
    7.     return *this;  
    8. }  



    六、析构函数

    是构造函数的互补,当对象超出作用域或动态分配的对象被删除时,将自动应用析构函数。析构函数可用于释放对象时构造或在对象的生命期中所获取的资源。不管类是否定义了自己的析构函数,编译器都会自动执行类中非static数据成员的析构函数。

    析构函数的运行:

    当对象引用或指针越界的时候不会执行析构函数,只有在删除指向动态分配对象的指针或实际对象超出作用域时才会调用析构函数。

    合成析构函数:

    编译器总是会合成一个析构函数,合成析构函数按对象创建时的逆序撤销每个非static成员。要注意的是,合成的析构函数不会删除指针成员所指向的对象。

     

    最后要注意的是:类如果需要析构函数,那么他肯定也需要复制构造函数和赋值操作符。

     

     

    blog的最后给出完整的六大函数的代码。

      1. #include <iostream>  
      2. #include <assert.h>  
      3. using namespace std;  
      4.   
      5. class Temp  
      6. {  
      7. public:  
      8.     Temp(const char* str = nullptr);  
      9.     Temp(Temp&& t);  
      10.     Temp& operator = (Temp&& t);  
      11.     Temp(const Temp& t);  
      12.     Temp& operator = (Temp& t);  
      13.     ~Temp(void);  
      14. private:  
      15.     char *m_pData;  
      16. };  
      17.   
      18. Temp::Temp(const char* str)  
      19. {  
      20.     if (!str)  
      21.     {  
      22.         m_pData = nullptr;  
      23.     }  
      24.     else  
      25.     {  
      26.         this->m_pData = new char[strlen(str) + 1];  
      27.         strcpy(this->m_pData, str);  
      28.     }  
      29. }  
      30.   
      31. Temp::Temp(Temp&& t) :m_pData(move(t.m_pData))  
      32. {  
      33.     t.m_pData = nullptr;  
      34. }  
      35.   
      36. Temp& Temp::operator = (Temp&& t)  
      37. {  
      38.     assert(this != &t);  
      39.   
      40.     this->m_pData = nullptr;  
      41.     this->m_pData = move(t.m_pData);  
      42.     t.m_pData = nullptr;  
      43.   
      44.     return *this;  
      45.   
      46. }  
      47.   
      48. Temp::Temp(const Temp& t)  
      49. {  
      50.     if (!t.m_pData)  
      51.     {  
      52.         this->m_pData = nullptr;  
      53.     }  
      54.     else  
      55.     {  
      56.         this->m_pData = new char[strlen(t.m_pData) + 1];  
      57.         strcpy(this->m_pData, t.m_pData);  
      58.     }  
      59. }  
      60.   
      61. Temp& Temp::operator = (Temp &t)  
      62. {  
      63.     if (this != &t)  
      64.     {  
      65.         delete[] this->m_pData;  
      66.         if (!t.m_pData)  
      67.         {  
      68.             this->m_pData = nullptr;  
      69.         }  
      70.         else  
      71.         {  
      72.             this->m_pData = new char[strlen(t.m_pData) + 1];  
      73.             strcpy(this->m_pData, t.m_pData);  
      74.         }  
      75.     }  
      76.   
      77.     return *this;  
      78. }  
      79.   
      80. Temp::~Temp(void)  
      81. {  
      82.     if (this->m_pData)  
      83.     {  
      84.         delete[] this->m_pData;  
      85.         this->m_pData = nullptr;  
      86.     }  
      87. }  
    posted @ 2018-02-05 16:18 史D芬周 阅读(...) 评论(...) 编辑 收藏
    展开全文
  • ...版权声明:本文为博主原创文章,未经博主允许不得转载。...在C++中,有三大函数复制控制(复制构造函数,赋值操作符,析构函数),而在C++11中,加入...我就斗胆将他们命名为六大函数好了。 一、构造函数 c
    转载自:http://blog.csdn.net/jofranks/article/details/17438955

    在C++中,有三大函数复制控制(复制构造函数,赋值操作符,析构函数),而在C++11中,加入了移动构造函数,移动赋值操作符。我就斗胆将他们命名为六大函数好了。

    一、构造函数

    c++primer中说过:构造函数是特殊的成员函数,只要创建类类型的新对象,都要执行构造函数。构造函数的工作就是保证每个对象的数据成员具有合适的初始值。

    构造函数与其他函数不同:构造函数和类同名,没有返回类型。

    构造函数与其他函数相同:构造函数也有形参表(可为void)和函数体。  (参数表为void的构造函数为默认构造函数)

    构造函数构造类对象的顺序是:1.内存分配,构造函数调用的时候 隐士\显示的初始化各数据。

    2.执行构造函数的运行。

    1、构造函数初始化表

    [cpp] view plain copy
    1. A() :a(0){}  
    我们使用构造函数初始化表示初始化数据成员,然而在没有使用初始化表的构造函数则在构造函数体中对数据成员赋值。

    在我们编写类的时候,有些成员必须在构造函数初始化表中进行初始化。(没有默认构造函数的类类型成员,const或者引用类型成员)

    在编写代码的时候,要注意的是:可以初始化const对象或者引用类型的对象,但不能对他们进行赋值。 也就是需要在我们执行构造函数函数体之前完成初始化工作,所以唯一的机会就是初始化表。从这一点可以看出初始化表的执行先于函数体。

    在初始化表中,成员被初始化的次序不是你编写初始化表的次序,而是定义成员的次序。


    初始化列表在初始化类类型的成员时,要指定实参并传递给成员类型的一个构造函数。

    在c++primer中有一个书店的例子:

    [cpp] view plain copy
    1. Sales-item(): isbn(10, '9'), units_sold(0), revenue(0.0) {}  


    我们的初始化表在什么时候必须使用呢 ?

    当有一个类成员,他本身就是结构或者类的时候,并且只有一个带参数的构造函数,(无默认构造函数) 此时我们要对成员进行初始化,就需要调用成员的构造函数,此时需要我们的初始化表,如果不使用初始化表,那么内存分配就会出问题。

    初始化列表的优点:主要是对于自定义类型,初始化列表是作用在函数体之前,他调用构造函数对对象进行初始化。

    然而在函数体内,需要先调用构造函数,然后进行赋值,这样效率就不如初始化表。



    2、默认实参构造函数

    [cpp] view plain copy
    1. A(int i = 1) :a(i), ca(i), ra(i){}  


    3、默认构造函数

    合成的默认构造函数:当类中没有定义构造函数(注意是构造函数)的时候,编译器自动生成的函数。

    但是我们不能过分依赖编译器,如果我们的类中有复合类型或者自定义类型成员,我们需要自己定义构造函数。

    自定义的默认构造函数:

    [cpp] view plain copy
    1. A(): a(0) {}  
    2. A(int i = 1): a(i) {}  
    可能疑问的是第二个构造函数也是默认构造函数么?是的,因为参数中带有默认值。

    我们来看一张图,就会一目了然了:


    4、类型转换

    在C++primer中,书店问题中的一个例子是 传递string对象或者iostream对象到参数中,会发生隐式转换,这样就会出现问题。

    explicit关键字可以抑制隐式转换。

    [cpp] view plain copy
    1. explicit Sales_item(const string &book): isbn(book) {}  

    如果我们声明了构造函数禁止隐式转换, 可以将其他对象显示转换后传入构造函数。

    [cpp] view plain copy
    1. string a = "d";  
    2. item.same(Sales_item(a));  

    二、移动构造函数

    在C++11中新加入的特性!

    在上一篇blog中我加入了一张图,可以具体看到移动构造函数的运行原理。


    此时,我们偷走了临时变量的内存空间,据为己用。节省了开辟空间的时间。

    [cpp] view plain copy
    1. A(A && h) : a(h.a)  
    2. {  
    3.     h.a = nullptr; //还记得nullptr?  
    4. }  

    可以看到,这个构造函数的参数不同,有两个&操作符,   移动构造函数接收的是“右值引用”的参数。

    还要来说一下,这里h.a置为空,如果不这样做,h.a在移动构造函数结束时候执行析构函数会将我们偷来的内存析构掉。h.a会变成悬垂指针

    移动构造函数何时触发?  那就是临时对象(右值)。用到临时对象的时候就会执行移动语义。

    这里要注意的是,异常发生的情况,要尽量保证移动构造函数 不发生异常,可以通过noexcept关键字,这里可以保证移动构造函数中抛出来的异常会直接调用terminate终止程序。

    右值引用:

    在上一篇blog中,我们提到过将亡值,他是c++11新增的跟右值引用相关的表达式。

    在c++11中,右值引用就是对一个右值进行引用的类型,右值通常不具有名字,我们就只能通过引用的方式找到它的存在了。

    比较一下下面两条语句:

    [cpp] view plain copy
    1. T &&a = returna();  
    2. T b = returnb();  
    此时a是右值引用,他比b少了一次对象析构和对象构造的过程。a直接绑定了returna返回的临时变量。b只是由临时变量值构造而成的。

    应该可以看清楚了吧。右值引用就是让返回的右值(临时对象)重获新生,延长生命周期。临时对象析构了,但是右值引用存活。

    不过要注意的是,右值引用不能绑定左值:int a; int &&c = a;   这样是不行的。


    这里有一个函数就是 move函数,它能够将左值强制转换成右值引用。


    三、移动赋值操作符

    他的原理跟移动构造函数相同,这里不再多说。

    给出实现代码:

    [cpp] view plain copy
    1. A & operator = (A&& h)  
    2. {  
    3.     assert(this != &h);  
    4.   
    5.     a = nullptr;  
    6.     a = move(h.a);  
    7.     h.a = nullptr;  
    8.     return *this;  
    9. }  



    复制控制

    四、复制构造函数

    他是一种特殊的构造函数,具有单个形参,形参是对该类类型的引用。当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式使用复制构造函数。当将该类型的对象传递给函数或从函数返回该类型的对象时,将隐式使用复制构造函数。

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

    1.、类有一个或者多个数据成员是指针。

    2、有成员表示在构造函数中分配的其他资源。另外的类在创建新对象时必须做一些特定的工作。

    下面给出赋值构造函数的编写:

    [cpp] view plain copy
    1. A(const A& h) :a(h.a){}  
    如果不想让对象复制呢? 那就将复制构造函数声明为:private;

    五、赋值操作符

    他跟构造函数一样,赋值操作符可以通过制定不同类型的右操作数而重载。

    赋值和复制经常是一起使用的,这个要注意。

    下面给出赋值操作符的写法:

    [cpp] view plain copy
    1. A& operator = (const A& h)  
    2. {  
    3.     assert(this != &h);  
    4.   
    5.     this->a = h.a;  
    6.   
    7.     return *this;  
    8. }  


    六、析构函数

    是构造函数的互补,当对象超出作用域或动态分配的对象被删除时,将自动应用析构函数。析构函数可用于释放对象时构造或在对象的生命期中所获取的资源。不管类是否定义了自己的析构函数,编译器都会自动执行类中非static数据成员的析构函数。

    析构函数的运行:

    当对象引用或指针越界的时候不会执行析构函数,只有在删除指向动态分配对象的指针或实际对象超出作用域时才会调用析构函数。

    合成析构函数:

    编译器总是会合成一个析构函数,合成析构函数按对象创建时的逆序撤销每个非static成员。要注意的是,合成的析构函数不会删除指针成员所指向的对象。


    最后要注意的是:类如果需要析构函数,那么他肯定也需要复制构造函数和赋值操作符。



    blog的最后给出完整的六大函数的代码。

    [cpp] view plain copy
    1. #include <iostream>  
    2. #include <assert.h>  
    3. using namespace std;  
    4.   
    5. class Temp  
    6. {  
    7. public:  
    8.     Temp(const char* str = nullptr);  
    9.     Temp(Temp&& t);  
    10.     Temp& operator = (Temp&& t);  
    11.     Temp(const Temp& t);  
    12.     Temp& operator = (Temp& t);  
    13.     ~Temp(void);  
    14. private:  
    15.     char *m_pData;  
    16. };  
    17.   
    18. Temp::Temp(const char* str)  
    19. {  
    20.     if (!str)  
    21.     {  
    22.         m_pData = nullptr;  
    23.     }  
    24.     else  
    25.     {  
    26.         this->m_pData = new char[strlen(str) + 1];  
    27.         strcpy(this->m_pData, str);  
    28.     }  
    29. }  
    30.   
    31. Temp::Temp(Temp&& t) :m_pData(move(t.m_pData))  
    32. {  
    33.     t.m_pData = nullptr;  
    34. }  
    35.   
    36. Temp& Temp::operator = (Temp&& t)  
    37. {  
    38.     assert(this != &t);  
    39.   
    40.     this->m_pData = nullptr;  
    41.     this->m_pData = move(t.m_pData);  
    42.     t.m_pData = nullptr;  
    43.   
    44.     return *this;  
    45.   
    46. }  
    47.   
    48. Temp::Temp(const Temp& t)  
    49. {  
    50.     if (!t.m_pData)  
    51.     {  
    52.         this->m_pData = nullptr;  
    53.     }  
    54.     else  
    55.     {  
    56.         this->m_pData = new char[strlen(t.m_pData) + 1];  
    57.         strcpy(this->m_pData, t.m_pData);  
    58.     }  
    59. }  
    60.   
    61. Temp& Temp::operator = (Temp &t)  
    62. {  
    63.     if (this != &t)  
    64.     {  
    65.         delete[] this->m_pData;  
    66.         if (!t.m_pData)  
    67.         {  
    68.             this->m_pData = nullptr;  
    69.         }  
    70.         else  
    71.         {  
    72.             this->m_pData = new char[strlen(t.m_pData) + 1];  
    73.             strcpy(this->m_pData, t.m_pData);  
    74.         }  
    75.     }  
    76.   
    77.     return *this;  
    78. }  
    79.   
    80. Temp::~Temp(void)  
    81. {  
    82.     if (this->m_pData)  
    83.     {  
    84.         delete[] this->m_pData;  
    85.         this->m_pData = nullptr;  
    86.     }  
    87. }  
    展开全文
  • 1. C++什么时候会调用 拷贝构造函数? a.一个对象作为函数参数,以值传递的方式传入函数体; b.一个对象作为函数返回值,以值传递的方式从函数返回;(实际使用时,会被编译器优化掉) c.一个对象用于给另外一个...

    1.  C++什么时候会调用 拷贝构造函数?

         a.一个对象作为函数参数,以值传递的方式传入函数体;

         b.一个对象作为函数返回值,以值传递的方式从函数返回;(实际使用时,会被编译器优化掉)

         c.一个对象用于给另外一个对象进行初始化(常称为赋值初始化)

            如:

    Animal a;
    Animal b(a);
    
    // 或者
    Animal a;
    Animal b = a;

    2. C++ 6大函数

       1.构造函数

       2.move构造函数

       3.move赋值操作符

       4.复制构造函数

       5.赋值操作符

       6.析构函数

    关于move构造函数 和 move赋值操作符,可以提高性能:

    // 测试 move
    class Animal{
        
    public:
        
        Animal(){}
        Animal(const char* name,int age){
            _age = age;
            _name = new char[strlen(name)];
            strcpy(_name,name);
        };
        
        // 拷贝构造函数
        Animal(const Animal& other){
            if (_name) {
                printf("[Animal  拷贝构造函数]看看会不会调用\n");
                delete [] _name;
                _name = nullptr;
            }
            
            cout << "[Animal Copy Constructor]  called" << endl;
            _name = new char[strlen(other._name)];
            strcpy(_name,other._name);
            _age = other._age;
        }
        
        // 赋值
        Animal& operator=(const Animal& other){
            
            if (this == &other) {
                return *this;
            }
            
            if (_name) {
                printf("[Animal   赋值]看看会不会调用\n");
                delete [] _name;
                _name = nullptr;
            }
            cout << "[Animal Assign Constructor]  called" << endl;
            _name = new char[strlen(other._name)];
            strcpy(_name,other._name);
            _age = other._age;
            return *this;
        }
        
        // move copy constructor
        Animal(Animal&& other){
            cout << "move copy constructor called." << endl;
            _name = other._name;
            _age = other._age;
            other._name = nullptr;
        }
        
        // move assign constructor
        Animal& operator=(Animal&& other){
            if (this == &other) {
                return *this;
            }
            
            if (_name) {
                delete [] _name;
                _name = nullptr;
            }
            
            cout << "move assign constructor called." << endl;
            _name = other._name;
            _age = other._age;
            other._name = nullptr;
            return *this;
        }
        
        void show(){
            cout << "name:" << _name << ";  age :" << _age << endl;
        }
    
        ~Animal(){
            cout << "Animal Deconstructor" << endl;
            if (_name) {
                delete [] _name;
            }
        }
       
    private:
        
        int _age = 0;
        char* _name = nullptr;
    };
    
    Animal genAnimal(){
        return Animal("wangwu",3);
    }

    测试:

    int main(){
    
        // 会调用 move copy constructor
        vector<Animal> V;
        V.push_back(Animal("zhangsan",1));
    
        // 会调用  move assign constructor
    //    Animal a("zhangsan",1);
    //    a = genAnimal();
        
        return 0;
    }

    主要需要明白什么时候调用   copy  constructor,什么时候调用 assign operator.

    转载于:https://www.cnblogs.com/daihanlong/p/4704915.html

    展开全文
  • 一 C++类六大成员函数 构造函数、析构函数、拷贝构造函数、移动构造函数、拷贝赋值、移动赋值。 以class A为例: // C++ 类的六大成员函数 class A { public: // 1. 构造函数 A(); // 2. 析构函数 ~A(); ...

    一   C++类六大成员函数

            构造函数、析构函数、拷贝构造函数、移动构造函数、拷贝赋值、移动赋值。

            以class A为例:

    // C++ 类的六大成员函数
    class A
    {
    public:
    	// 1. 构造函数
    	A();
    	// 2. 析构函数
    	~A();
    	// 3. 拷贝构造函数
    	A(const A &);
    	// 4. 移动构造函数
    	A(A &&);
    	// 5. 拷贝赋值函数
    	A &operator=(const A &);
    	// 6. 移动赋值函数
    	A &operator=(A &&);
    };

    二   C++类默认有的六大成员函数

            缺省构造函数、析构函数、拷贝构造函数、拷贝赋值函数、取址运算符重载、const修饰的取址运算符重载

            以空类class Empty为例:

    // 一个空类默认就有的六大成员函数
    class Empty
    {
    public:
    /*
    	// 1. 缺省构造函数
    	Empty(){}
    	// 2. 拷贝构造函数
    	Empty(const Empty&){}
    	// 3. 析构函数
    	~Empty(){}
    	// 4. 拷贝赋值函数
    	Empty &operator=(const Empty &){}
    	// 5. 取址运算符
    	Empty *operator&(){}
    	// 5. 取址运算符const
    	const Empty *operator&()const{}
    */
    };

     

    展开全文
  • 我就斗胆将他们命名为六大函数好了。 一、构造函数 c++primer中说过:构造函数是特殊的成员函数,只要创建类类型的新对象,都要执行构造函数。构造函数的工作就是保证每个对象的数据成员具有合适的初始值。 构造...
  • 我们知道大神们在设计C++时候就给C++有个默认的函数,所谓默认就是,无需我们这些程序猿们动手去写,仅仅要你在将类实例化。即创建一个对象,在利用对象进行数据操作时候,就会编译器自己主动调用默认的函数,可是...
  • C和C++ 1.C+调用C语言: extern "C" { 包含在里面的代码以C语言...2.封装:隐藏了对象的属性和实现细节,对外提供公有接口,供函数使用。【getname()接口】 访问限定符: public: 任意 protected:本类和子类...
  • 1.拷贝构造函数和移动构造函数 总的来说,都是用一个已有的对象去创建构造一个新的对象。 当对象中含有指针或类作为数据成员的,对于已有的对象在构造出新的对象后,仍需要对该已有对象进行引用或利用的,需要我们...
  • 函数

    2019-08-31 20:58:15
    函数参数的值传递和引用 1. 值传递:函数将参数复制一份(实参复制给形参),函数内部操作的是形参,对实参没有影响 2. 引用:函数传入的地址,实参和形参指向同一个变量 int fun(int a) { a = 2; } int fun(int *a...
  • 六大成员函数 构造函数 **功能:**在已有空间上初始化对象成员变量 1.如果没有显示定义,编译器会自动生成,如果定义了任何一个构造函数,编译器都不会再自动生成 2.构造函数支持重载 3.默认构造:无参、全缺省、...
  • 课 新建Photoshop图像 教学目标1熟悉Photoshop的工作界面 2提高学生的信息技术水平 教学重点1熟悉Photoshop的工作界面 2新建图画文件 3了解及运用画笔填充工具 4文件的定向保存 教学难点画笔填充工具的运用 课?...
  • 类的六大默认成员函数

    千次阅读 2016-06-02 15:43:30
    1. 构造函数 如果类的成员变量为私有的,要对这些成员初始化必须调用一个共有的成员函数来进行. 这个共有的成员函数在定义对象的同时会自动执行一次,被调用的函数称为构造函数. 构造函数的特点: 1.函数名与类名...
  • 六大默认成员函数类的 6 个默认成员函数构造函数析构函数拷贝构造函数运算符重载普通运算符重载函数赋值运算符重载函数const成员取地址及const取地址操作符重载总结 类的 6 个默认成员函数 初始化和清理: 构造函数...
  • 以上就是类的六大默认的成员函数,这篇博客主要讲构造函数。剩下的五个成员函数后边会持续更出    构造函数 一.构造函数的定义  构造函数是一个特殊的...
  • 类的六大默认构造函数

    千次阅读 2018-03-03 00:11:22
    缺省的构造函数和析构函数,等于放弃了自己初始化和清除的机会;缺省的拷贝构造和缺省的赋值函数,采用“位拷贝和值拷贝”。若类中出现指针时,这两个函数出错。 class String { public: String(const char *str =...
  • C++ STL六大组件-5-Function object(函数对象)C++ STL Function object如果一个类将()运算符重载为成员函数,这个类就称为函数对象类,这个类的对象就是函数对象。函数对象是一个对象,但是使用的形式看起来像函数...
  • 函数

    2020-03-25 22:26:23
    2、将复杂的问题分解成一系列小问题,分而治之——模块化设计的思想 3、利于代码的维护和管理 函数的定义及调用 白箱子:输入——处理——输出 三要素:参数、函数体、返回值 1、定义 def 函数名(参数):   ...
  • 构造函数 构造函数:在已有空间上初始化对象成员变量 1.如果没有定义,编译器自动生成,如果定义了 任何一个构造函数,编译器不在自动生成 2.支持重载 3.默认构造:无参, 全缺省,编译器自动生成的,三者只能存在一个...
  • 函数函数编程 为便于代码维护,绝多数子程序都被分解并重新组织为函数以使代码模块化。 在Python 中定义一个函数很简单,Python从其它函数编程语言中借鉴了很多有用的思路用来简化某些特定任务。本章的...
  • 、单行函数

    2020-12-02 19:16:09
    、单行函数SQL函数两种函数单行函数字符函数数字函数日期函数多行函数转化函数隐式数据类型转换显式数据类型转换通用函数条件表达式CASE 表达式DECODE 函数**嵌套函数**总结 SQL函数 两种函数 单行函数 单行函数...
  • c++中的六大缺省函数

    千次阅读 2016-07-04 21:40:18
    #include #include using namespace ..."调用构造函数" ..."调用构造函数" ..."调用拷贝构造函数" ...C++中的六大缺省函数 构造函数 拷贝构造函数 赋值函数 析构函数 普通方法的重载& 常方法的重载&
  • 析构函数 一.析构函数定义  析构函数也是特殊的成员函数,他的作用和构造函数相反。 class Box { public: //构造函数 Box(int h,int w,int l); //析构函数 ~Box(); private: int height; i...
  • 函数基础

    2018-01-18 18:09:00
    函数基础 一、函数的定义  函数就是对代码进行一个封装。把实现,某一功能的相同代码,进行封装到一起。下次需要使用时,就不需要再进行代码编写,直接调用即可。  内置函数就是把一些需求量比较的...
  • C++ STL六大组件-5-Function object(函数对象)C++ STL Function object如果一个类将()运算符重载为成员函数,这个类就称为函数对象类,这个类的对象就是函数对象。函数对象是一个对象,但是使用的形式看起来像函数...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,128
精华内容 2,051
关键字:

六大函数