• C++ 拷贝构造函数和赋值运算符


      这篇文章主要介绍拷贝构造函数和赋值运算符的区别,以及在什么时候调用拷贝构造函数,什么情况下调用赋值运算符。    

      拷贝构造函数和赋值运算符

      在默认情况下(用户没有定义,但是也没有显示的删除),编译器会自动隐式生成一个拷贝构造函数和赋值运算符,但用户可以使用delete来指定不生成拷贝构造函数和赋值运算符,这样的对象就不能通过值传递,也不能进行赋值运算

     1 #include <iostream>
     2 
     3 using namespace std;
     4 class Person {
     5 public:
     6     Person():{}
     7     Person(const Person& p) = delete;
     8     Person& operator= (const Person& p) = delete;
     9 
    10     void SetName( string  strName ) 
    11     {
    12         name = strName;
    13     }
    14     void SetAge(int nAge)
    15     {
    16         age = nAge;
    17     }
    18 private:
    19     int age;
    20     string name;
    21 };
    22 int main()
    23 {
    24     Person p1;
    25     p1.SetName("air");
    26     p1.SetAge(18);
    27 
    28     //Person p2(p1);   错误的
    29     return 0;
    30 }

    上面定义的类Person显式的删除了拷贝构造函数和赋值运算符,在需要调用拷贝构造函数或者赋值运算符的地方,会提示无法调用该函数,它是已删除的函数。

    还有一点需要注意的是,拷贝构造函数必须以引用的方式传递参数,这是因为,在值传递给一个函数的时候,会调用拷贝构造函数生成函数的实参,如果拷贝构造函数的参数仍然是以值的方式,就会无限循环的调用下去,直到函数的栈溢出。

    何时调用

      拷贝构造函数和赋值运算符的行为比较相似,都是将一个对象的值复制给另一个对象,但是其结果却有些不同,拷贝构造函数使用传入对象的值生成一个新的对象的实例,而赋值运算符是将对象的值复制给一个已经存在的实例。这种区别从两者的名字也能轻易的分辨出来,拷贝构造函数也是一种构造函数,那么它的功能就是创建一个新的对象实例;赋值运算符是执行某种运算,将一个对象的值复制给另一个对象(已经存在的)。调用的是拷贝构造函数还是赋值运算符,主要是看是否有新的对象实例产生,如果产生了新的对象实例,那调用的就是拷贝构造函数;如果没有,那就是对已有的对象赋值,调用的是赋值运算符。

    调用拷贝构造函数主要有以下场景:

      1:对象作为函数的参数,以值传递的方式传给函数。

      2:对象作为函数的返回值,以值的方式从函数返回。

      3:使用一个对象给另一个对象初始化。

    代码如下:

     1 #include <iostream>
     2 
     3 using namespace  std;
     4 class Person
     5 {
     6 public:
     7     Person() {}
     8     Person( const Person& p )
     9     {
    10         cout << "Copy Constructor" << endl;
    11     }
    12 
    13     Person& operator=( const Person& p )
    14     {
    15         cout << "Assign" << endl;
    16         return *this;
    17     }
    18 
    19 private:
    20     int age;
    21     string name;
    22 };
    23 
    24 void f( Person p )
    25 {
    26     return;
    27 }
    28 
    29 Person f1( )
    30 {
    31     Person p;
    32     return p;
    33 }
    34 
    35 
    36 int main()
    37 {
    38     Person p;
    39     Person p1 = p;    //  1 
    40     Person p2;  //
    41     p2 = p;           // 2
    42     f(p2);            // 3
    43 
    44     p2 = f1();        // 4
    45 
    46     Person p3 = f1(); // 5
    47 
    48     return 0;
    49 }

     

    1:虽然使用了“=”,但是实际上使用对象p来创建了一个新的对象p1.也就是产生了新的对象,所以调用的是拷贝构造函数。

    2:首先声明了一个对象p2,然后使用复制运算符"=",将p的值赋值给p2,显然是调用了赋值运算符,为一个已经存在的对象赋值。

    3:以值传递的方式将对象p2传入函数f内,调用拷贝构造函数构建一个函数f可用的实参

    4:这条语句拷贝构造函数和赋值运算符都调用了。函数f1以值的方式返回一个Person对象,在返回时会调用拷贝构造函数创建一个临时对象tmp作为返回值;返回后调用赋值运算符将临时对象tmp赋值给p2.

    5:应该是首先调用拷贝构造函数创建临时对象;然后再调用拷贝构造函数使用刚才创建的临时对象创建新的对象p3,也就是会调用两次拷贝构造函数。不过,编译器也没有那么傻,应该是直接调用拷贝构造函数使用返回值创建了对象p3。

  • 相关阅读:
    db_block_checking与db_block_checksum
    Provider=SQLNCLI10.1;Integrated Security="";Persist Security Info=False;User ID=sa;Initial Catalog=Depot;Data Source=192
    Delphi 获取文件路径
    ip地址查询方法
    SQL Server ADOConnectionString 怎么写
    jQuery 中的 attr
    【转】 JavaScript中With 语句使用方法实例
    【转】JS获取字符串长度(区分中英文)
    【转】ASP.NET 页面之间传递值的几种方式
    jQuery hover事件
  • 原文地址:https://www.cnblogs.com/cxq0017/p/10620273.html
Copyright © 2020-2023  润新知