条款5:了解C++默认编写并调用哪些函数

来源:互联网 发布:发票验旧需要什么数据 编辑:程序博客网 时间:2024/06/05 08:51
条款5:了解C++默认编写并调用哪些函数

1、空类

    空类本来是没有存储空间,但为了能在内存中找到该类,编译器为该类添加一个char类型的成员,用来唯一标识该类在内存的位置
编译器为空类自定义哪些函数,这些函数都是public并且inline
①默认构造函数
②默认析构函数
③默认拷贝构造函数
④默认拷贝赋值函数

2、默认构造函数

    当我们自定义构造函数,编译器就不会为我们定义一个缺省构造函数

3、默认析构函数

    只有当基类定义virtual析构函数,继承的derive class才默认具有虚属性,条款7会详细介绍。

4、默认拷贝构造函数

    C++中对象的复制就如同“克隆”,用一个已有的对象快速地复制出多个完全相同的对象。一般而言,以下三种情况都会使用到对象的复制:
①建立一个新对象,并用另一个同类的已有对象对新对象进行初始化
②当函数的参数为类的对象时,这时调用此函数时使用的是值传递,也会产生对象的复制;
③函数的返回值是类的对象时,在函数调用结束时,需要将函数中的对象复制一个临时对象并传给改函数的调用处。

默认拷贝构造函数仅仅使用“老对象”的数据成员的值对“新对象”的数据成员一一进行赋值
class Book{private:std::string m_name;int m_id;};Book s1;Book s2 = s1;  //调用编译器的拷贝构造函数,复制一本书//编译器为我们生成的拷贝构造函数Book(const Book &r){this->m_name = r.m_name;  //调用string类的拷贝构造函数完成this->m_id = r.m_id;}
类中有静态成员
如果让一个静态成员统计该种书的数量会是什么情况呢?
class Book{public:<span style="white-space:pre"></span>Book() {++m_iCount;}<span style="white-space:pre"></span>~Book() {--m_iCount;}private:<span style="white-space:pre"></span>std::string m_name;<span style="white-space:pre"></span>int m_id;<span style="white-space:pre"></span>static int m_iCount;};
那么不管我们复制多少本书,最终计数还是1,而且析构书时,计数变成负数

类中有动态数据成员
浅拷贝

    所谓浅拷贝,指的是在对象复制时,只是对对象中的数据成员进行简单的赋值,上面的例子都是属于浅拷贝的情况,默认拷贝构造函数执行的也是浅拷贝。但是一旦对象存在了动态成员,那么浅拷贝就会出问题。

class Book{public:Book(const char *name, const int id) :m_id(id){m_name = new char[strlen(name) + 1];strcpy(this->m_name, name);}~Book() {if (m_name != NULL)delete[] m_name;m_name = NULL; //可防止同一个对象内存被释放两次}private:char *m_name;const int m_id;};
        Book s1("match", 1);Book s2 = s1;
    s2调用默认拷贝构造函数,s2.m_name与s1.m_name指向同一个内存区域,即任意一个对值m_name的操作都会影响到另一个,而且还可能导致同一块内存被释放两次.这种情况,需要“深拷贝”来解决。

深拷贝

    深拷贝就不是简单的赋值,而且重新分配一块空间,这就需要我们自定义拷贝构造函数和拷贝赋值函数

在Book类中定义拷贝构造函数:

Book(const Book & book):m_id(book.m_id){this->m_name = new char[strlen(book.m_name) + 1];strcpy(this->m_name, book.m_name);}

5、默认拷贝赋值函数

class Book{public:Book(std::string &name, const int id) :m_name(name), m_id(id){}~Book() {}private:std::string &m_name;const int m_id;};
调用
std::string str1 = "match";std::string str2 = "telno";Book s1(str1, 1);Book s2(str2, 2);s2 = s1;
    s2调用默认拷贝赋值函数,但赋值函数是对每一个成员赋值,类中有const和引用成员,在C++中是不允许重新赋值的,编译器会报错,因此在类中有引用成员和常量成员,需要自定义赋值函数,或者禁用它,下个条款说明。


0 0