❥关于C++之类的复制构造函数&赋值运算符

Posted itzyjr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了❥关于C++之类的复制构造函数&赋值运算符相关的知识,希望对你有一定的参考价值。

C++自动提供了下面这些成员函数:

  • 默认构造函数,如果没有定义构造函数
  • 默认析构函数,如果没有定义
  • 复制构造函数,如果没有定义
  • 赋值运算符,如果没有定义
  • 地址运算符,如果没有定义

一、复制构造函数

复制构造函数用于将一个对象复制到新创建的对象中。

类的复制构造函数原型:_Class(const _Class &);

它接受一个指向类对象的常量引用作为参数。例如,StringBad类的复制构造函数的原型如下:

StringBad(const StringBad &);

何时调用复制构造函数?

StringBad ditto(motto); // 调用StringBad(const StringBad &)
StringBad metoo = motto; // 调用StringBad(const StringBad &)
StringBad also = StringBad(motto); // 调用StringBad(const StringBad &)
StringBad *pStringBad = new StringBad(motto); // 调用StringBad(const StringBad &)
如果重载了operator+(),则下面语句将调用复制构造函数:
StringBad x, y, z;
x + y = z; // x + y创建临时对象再被赋值z,创建临时对象时调用StringBad(const StringBad &)

每当程序生成了对象副本时,编译器都将使用复制构造函数。

在下述情况下,将使用复制构造函数:

  • 将新对象初始化为一个同类对象;
  • 按值将对象传递给函数;
  • 函数按值返回对象;
  • 编译器生成临时对象。

实现一个复制构造函数:

StringBad::StringBad(const StringBad & st) 
    num_strings++; // 处理静态成员的更新
    len = st.len;
    str = new char[len + 1]; // 分配空间
    std::strcpy(str, st.str); // 复制字符串到新地址
    cout << num_strings << ":\\"" << str << "\\" object created\\n";

二、赋值运算符

并不是程序清单的所有问题都可以归咎于默认的复制构造函数,还需要看一看默认的赋值运算符。ANSI C允许结构赋值,而C++允许类对象赋值,这是通过自动为类重载赋值运算符实现的。这种运算符的原型:_Class & _Class::operator=(const _Class &);

它接受并返回一个指向类对象的引用。例如,StringBad类的赋值运算符的原型如下:

StringBad & StringBad::operator=(const StringBad &);

不要将赋值与初始化混淆了:

Star sirius;
Star alpha = sirius; // 初始化为一个对象
Star dogstar;
dogstar = sirius; // 赋值

如果语句创建新的对象,则使用初始化;如果语句修改已有对象的值,则是赋值。

何时调用赋值运算符?

将已有的对象赋给另一个对象时,将使用重载的赋值运算符:

StringBad headline1("Celery Stalks at Midnight");
...
StringBad knot; // 自动调用默认构造函数初始化knot
knot = headline1; // 赋值运算符被调用

初始化对象时,并不一定会使用赋值运算符:

StringBad metoo = knot; // 使用复制构造函数,也可能使用的是赋值运算符

与复制构造函数相似,赋值运算符的隐式实现也对成员进行逐个复制。对象赋值是通过默认赋值运算符函数实现的(如果没有重载),把对象A的数据成员的值逐位赋值给对象B,两个对象之间的赋值,仅仅使用这些对象中数据成员,而两个对象仍是分离的。如果成员本身就是类对象,则程序将使用为这个类定义的赋值运算符来复制该成员,但静态数据成员不受影响。

实现一个赋值运算符:

StringBad & StringBad::operator=(const StringBad & st) 
    if (this == &st)
        return *this;
    delete[] str;
    len = st.len;
    str = new char[len + 1];
    std::strcpy(str, st.str);
    return *this;

由于赋值运算符,是处理对象的复制,将对象的字段深度复制过来即可,不涉及创建新对象,所以实现代码里没有 num_strings++; 这样的代码。但对于自定义的复制构造函数而言,不管是临时对象,还是用另一对象初始化一个对象,都涉及创建新对象,所以有代码 num_strings++; 方便跟踪以及计数逻辑。

以上是关于❥关于C++之类的复制构造函数&赋值运算符的主要内容,如果未能解决你的问题,请参考以下文章

如何利用模板复制&移动构造函数和赋值运算符?

C++学习之类的构造函数析构函数

C++类的成员函数:构造析构拷贝构造运算符重载

C++类的成员函数:构造析构拷贝构造运算符重载

C++类的成员函数:构造析构拷贝构造运算符重载

C++类的成员函数:构造析构拷贝构造运算符重载