美文网首页
C++ 编程技巧与规范(二)

C++ 编程技巧与规范(二)

作者: e196efe3d7df | 来源:发表于2020-11-19 15:30 被阅读0次

拷贝构造函数和拷贝复制运算符的书写

如下:

namespace demo2 {
    class A {
    public:
        A():m_i(0), m_j(0) {}
        A(int i, int j):m_i(i), m_j(j) {}

        A(const A& temp) {
            m_i = temp.m_i;
            m_j = temp.m_j;
        }

        A& operator=(const A& temp)
        {
            m_i = temp.m_i;
            m_j = temp.m_j;
            return *this;
        }

    public:
        int m_i;
        int m_j;
    };
}

int main()
{
    demo2::A a1;
    demo2::A a2 = a1;   //拷贝构造
    demo2::A a3;
    a3 = a1;            //拷贝赋值
}

对象自我赋值产生的问题

对象的自我赋值,会产生一些问题,比如:

#pragma warning(disable:4996) //strcpy会触发4996警告,头部加入 #pragma warning(disable:4996) 即可
namespace demo3 {
    class A {
    public:
        A() :m_i(0), m_j(0), m_charPtr(new char[100]){}
        A(int i, int j) :m_i(i), m_j(j), m_charPtr(new char[100]) {}

        A(const A& temp) {
            m_charPtr = new char[100];
            memcpy(m_charPtr, temp.m_charPtr, 100);
            m_i = temp.m_i;
            m_j = temp.m_j;
        }

        A& operator=(const A& temp)
        {
            delete m_charPtr;

            m_charPtr = new char[100];
            memcpy(m_charPtr, temp.m_charPtr, 100);
            m_i = temp.m_i;
            m_j = temp.m_j;
            return *this;
        }

    public:
        int m_i;
        int m_j;
        char* m_charPtr;
    };
}

int main()
{
    demo3::A a;
    strcpy(a.m_charPtr, "abcdef"); //strcpy会触发4996警告,头部加入 #pragma warning(disable:4996) 即可
    a = a;
}

A的赋值运算符重载函数,会先清理自身的m_charPtr,然后重新分配内存,把目标的m_charPtr赋值给自身的m_charPtr。当自我赋值时,会目标对象和自身对象是同一块内存,所以清理后,数据丢失,无法进行复制。可以进行如下改动

  1. 如果是同一对象的自我赋值,则直接返回自身。
A& operator=(const A& temp)
{
    if (this == &temp)
    {
        return *this;
    }

    delete m_charPtr;

    m_charPtr = new char[100];
    memcpy(m_charPtr, temp.m_charPtr, 100);
    m_i = temp.m_i;
    m_j = temp.m_j;
    return *this;
}
  1. 先把目标对象的资源复制一份,然后用复制的资源进行赋值。
A& operator=(const A& temp)
{
    char* tempCharPtr = new char[100];
    memcpy(tempCharPtr, temp.m_charPtr, 100);

    delete m_charPtr;

    m_charPtr = tempCharPtr;
    m_i = temp.m_i;
    m_j = temp.m_j;
    return *this;
}

第一种,简单明了。第二种,效率可能会更高

继承关系下拷贝构造函数和拷贝复制运算符的书写

如果在子类中没有定义自己的拷贝构造函数和拷贝复制运算符函数,则编译器会调用父类的拷贝构造函数和拷贝复制运算符函数。
反之,如果子类中定义自己的拷贝构造函数和拷贝复制运算符函数,则编译器会调用子类字自身的拷贝构造函数和拷贝复制运算符函数,不再调用父类的拷贝构造函数和拷贝复制运算符函数,需要程序员自己去调用父类的拷贝构造函数和拷贝复制运算符函数。如下:

namespace demo4 {
    class A {
    public:
        A() :m_i(0), m_j(0), m_charPtr(new char[100]) {}
        A(int i, int j) :m_i(i), m_j(j), m_charPtr(new char[100]) {}

        A(const A& temp) {
            m_charPtr = new char[100];
            memcpy(m_charPtr, temp.m_charPtr, 100);
            m_i = temp.m_i;
            m_j = temp.m_j;
        }

        A& operator=(const A& temp)
        {
            char* tempCharPtr = new char[100];
            memcpy(tempCharPtr, temp.m_charPtr, 100);

            delete m_charPtr;

            m_charPtr = tempCharPtr;
            m_i = temp.m_i;
            m_j = temp.m_j;
            return *this;
        }
        
        virtual ~A() {}

    public:
        int m_i;
        int m_j;
        char* m_charPtr;
    };

    class B :public A {
    public:
        B() {}
        ~B(){}

        B(const B& temp) :A(temp) {
            //A(temp) 不能将调用父类复制构造函数放在此处,会造成二义性,编译错误,编译器会解析成 A temp;
        }

        B& operator=(const B& temp) {
            A::operator=(temp);
            return *this;
        }       
    };
}

int main()
{
    demo4::B b1;
    demo4::B b2 = b1;   //拷贝构造函数
    b2 = b1;            //拷贝赋值运算
}

拷贝构造函数和拷贝复制运算符中重复代码的处理

不建议拷贝构造函数和拷贝复制运算符函数互相调用

相关文章

  • C++ 编程技巧与规范(二)

    拷贝构造函数和拷贝复制运算符的书写 如下: 对象自我赋值产生的问题 对象的自我赋值,会产生一些问题,比如: A的赋...

  • C++ 编程技巧与规范(五)

    不能被拷贝构造和拷贝赋值的类对象 delete 用delete这种方式,需要自己提供构造函数。 加入以上处理后,当...

  • C++ 编程技巧与规范(一)

    静态对象的探讨 类中静态成员变量 静态成员变量,需要先声明,然后再定义。如果没有使用到该静态成员变量,则可以不用定...

  • C++ 编程技巧与规范(四)

    组合关系 has-a 关系 has-a 关系也称为 is-part-of关系。下面的定义了这种关系: 可以是说是 ...

  • C++ 编程技巧与规范(三)

    类的public继承(is-a关系)及代码编写规范 子类继承父类的方式有三种:public, protected,...

  • 极客班第一周学习笔记

    初识C++ C++是在C之上基于对象,面向对象的编程语言。c++相比c在编程上更加模块化,具象化。 C++代码规范...

  • C++面向对象高级编程(上)笔记

    1.培养规范、大气的编程习惯 C++的学习过程可以分为C++语言与C++标准库两个部分,不必太在乎版本。标准库一般...

  • Boolan C++面向对象高级编程(上)第一周

    一、C++编程简介 C++ 98(1.0) C++ 11(2.0) 二、头文件与类的说明 1.基于对象与面向对象 ...

  • C++ 编程规范

    C++ 编程规范 这是一本 由两位世界顶级专家联袂巨献,适合所有层次 C++程序员 的 C++ 界20年集大成之作...

  • C++ 编程规范

    组织 不要拘泥于小节 在高警告级别干净利落地进行编译 使用自动构建系统 适用版本控制系统 在代码审查上投入 设计 ...

网友评论

      本文标题:C++ 编程技巧与规范(二)

      本文链接:https://www.haomeiwen.com/subject/agbkiktx.html