C++ :类 和 对象 ※重点※(二)

简介: C++ :类 和 对象 ※重点※(二)

析构函数:

  析构函数同样也是特殊的成员函数,首先它的功能是和构造函数相反的,但他不是去销毁对象,对象销毁的工作是由编译器去做的,析构函数是去完成资源的清理工作,在对象销毁的时候自动调用


析构函数的特性:

  1. 函数名是在类名前面加上 ‘~’
  2. 无参数且无返回值
  3. 一个类有且只有一个析构函数,如果没有显示定义编译器会自动生成
  4. 一个对象生命周期结束,自动调用析构函数


大家看我下面的代码:我定义的对象里面的那三个成员变量会用到默认生成的析构函数嘛

class stu
{
public:
  stu(int a = 10,char c = 'A',int b = 20)
  {
    _a = a;
    _c = c;
    _b = b;
  }
  void print()
  {
    cout << _a << "-" << _c << "-" << _b << endl;
  }
private:
  int _a;
  char _c;
  int _b;
};
int main()
{
  stu s1;
}

 这三个成员变量是不是我们的对象销毁的时候,它会自动的销毁啊,那我析构函数是去完成资源的清理的,那是不是malloc 那几个函数 还有new 以及fopen 这些才是析构函数要处理的阿,


  注意:我们编译器默认生成的析构函数对malloc那些函数开辟的空间是不会自动去释放的,这些是需要我们自己手动去写的,这也是因为它无法判断一个指针到底是不是一块内存空间的地址,默认生成的析构函数对于内置类型不做处理,自定义类型调用它的析构函数:

01a6a6cefca74af1b9f4dba47f431d59.png

class stu
{
public:
  stu(int a = 10,char c = 'A',int b = 20)
  {
    _a = a;
    _c = c;
    _b = b;
  }
  void print()
  {
    cout << _a << "-" << _c << "-" << _b << endl;
  }
private:
  int _a;
  char _c;
  int _b;
};
int main()
{
  stu s1(20,'B',30);
    stu s2(40,'C',50);
}

大家觉得这里的 s1和s2 谁先析构呢?

当然是s2会先析构 ,记得:析构顺序和构造的顺序是相反的


拷贝构造函数:

  这个也是一个特殊的构造函数,它是构造函数的一种重载,它是拿一个已经定义好的对象去定义另外一个对象,同样他也是默认成员函数的一名,不写编译器自动生成:

对于内置类型(指针也是)会完成值(浅)拷贝,自定义类型会去调用它的拷贝构造(自己写的也会调用,哪怕你的函数里面没有写它的拷贝)

class stu
{
public:
    stu(stu& d)
    {
        _a = d._a;
    _c = d._c;
    _b = d._b;
    }
  stu(int a = 10,char c = 'A',int b = 20)
  {
    _a = a;
    _c = c;
    _b = b;
  }
  void print()
  {
    cout << _a << "-" << _c << "-" << _b << endl;
  }
private:
  int _a;
  char _c;
  int _b;
};
int main()
{
  stu s1(20,'B',30);
    stu s2(s1);//s2 s3都是调用的拷贝构造函数
    stu s3 = s2;
}

注意:拷贝构造函数的参数只有一个并且必须使用引用传参,如果是传值传参会发生无限递归

c82cc64acf044bf8ba74a711c1770e37.png   对于那写内置类型的拷贝,都是按字节直接拷贝过去的,对于自定义类型,拷贝初始化规定要调用拷贝构造函数,至于其中的原因就涉及深浅拷贝的问题,就好像我malloc的空间的指针,如果直接赋值(浅拷贝),我两个对象的指针都指向的是同一块空间,那我在调用析构函数的时候,同一块空间被释放两次不就出问题了嘛,我们就得自己去实现拷贝构造

如果我们拷贝的成员里面又数组会报错嘛? :答案是不会的,我们数组拷贝又不是把数组的地址拷贝过去,拷贝的是数组里面的内容

我们的拷贝构造函数同样也是构造函数,他是我们平常写的构造函数的一种重载,我们如果类里面写了拷贝构造函数,那么编译器默认生成的构造函数就不会生成了!


还有一个问题就是涉及const的问题,通常我们在写的时候,如果自己写错了,写成了对 d对象 的成员变量赋值,那不就出错了嘛,所以我们要在拷贝构造的参数用const修饰一下,其实像这样我们不会改变的对象,加上const是最好的

class stu
{
public:
    stu(const stu& d)
    {
        _a = d._a;
    _c = d._c;
    _b = d._b;
    }
  stu(int a = 10,char c = 'A',int b = 20)
  {
    _a = a;
    _c = c;
    _b = b;
  }
  void print()
  {
    cout << _a << "-" << _c << "-" << _b << endl;
  }
private:
  int _a;
  char _c;
  int _b;
};
int main()
{
  stu s1(20,'B',30);
    stu s2(s1);//s2 s3都是调用的拷贝构造函数
    stu s3 = s2;
}


目录
相关文章
|
1天前
|
编译器 C++
【C++】string类的使用④(字符串操作String operations )
这篇博客探讨了C++ STL中`std::string`的几个关键操作,如`c_str()`和`data()`,它们分别返回指向字符串的const char*指针,前者保证以&#39;\0&#39;结尾,后者不保证。`get_allocator()`返回内存分配器,通常不直接使用。`copy()`函数用于将字符串部分复制到字符数组,不添加&#39;\0&#39;。`find()`和`rfind()`用于向前和向后搜索子串或字符。`npos`是string类中的一个常量,表示找不到匹配项时的返回值。博客通过实例展示了这些函数的用法。
|
1天前
|
存储 C++
【C++】string类的使用③(非成员函数重载Non-member function overloads)
这篇文章探讨了C++中`std::string`的`replace`和`swap`函数以及非成员函数重载。`replace`提供了多种方式替换字符串中的部分内容,包括使用字符串、子串、字符、字符数组和填充字符。`swap`函数用于交换两个`string`对象的内容,成员函数版本效率更高。非成员函数重载包括`operator+`实现字符串连接,关系运算符(如`==`, `&lt;`等)用于比较字符串,以及`swap`非成员函数。此外,还介绍了`getline`函数,用于按指定分隔符从输入流中读取字符串。文章强调了非成员函数在特定情况下的作用,并给出了多个示例代码。
|
1天前
|
C++
【C++】string类的使用④(常量成员Member constants)
C++ `std::string` 的 `find_first_of`, `find_last_of`, `find_first_not_of`, `find_last_not_of` 函数分别用于从不同方向查找目标字符或子串。它们都返回匹配位置,未找到则返回 `npos`。`substr` 用于提取子字符串,`compare` 则提供更灵活的字符串比较。`npos` 是一个表示最大值的常量,用于标记未找到匹配的情况。示例代码展示了这些函数的实际应用,如替换元音、分割路径、查找非字母字符等。
|
1天前
|
C++
C++】string类的使用③(修改器Modifiers)
这篇博客探讨了C++ STL中`string`类的修改器和非成员函数重载。文章介绍了`operator+=`用于在字符串末尾追加内容,并展示了不同重载形式。`append`函数提供了更多追加选项,包括子串、字符数组、单个字符等。`push_back`和`pop_back`分别用于在末尾添加和移除一个字符。`assign`用于替换字符串内容,而`insert`允许在任意位置插入字符串或字符。最后,`erase`函数用于删除字符串中的部分内容。每个函数都配以代码示例和说明。
|
1天前
|
安全 编译器 C++
【C++】string类的使用②(元素获取Element access)
```markdown 探索C++ `string`方法:`clear()`保持容量不变使字符串变空;`empty()`检查长度是否为0;C++11的`shrink_to_fit()`尝试减少容量。`operator[]`和`at()`安全访问元素,越界时`at()`抛异常。`back()`和`front()`分别访问首尾元素。了解这些,轻松操作字符串!💡 ```
|
1天前
|
存储 编译器 Linux
【C++】string类的使用②(容量接口Capacity )
这篇博客探讨了C++ STL中string的容量接口和元素访问方法。`size()`和`length()`函数等价,返回字符串的长度;`capacity()`提供已分配的字节数,可能大于长度;`max_size()`给出理论最大长度;`reserve()`预分配空间,不改变内容;`resize()`改变字符串长度,可指定填充字符。这些接口用于优化内存管理和适应字符串操作需求。
|
1天前
|
C++ 容器
【C++】string类的使用①(迭代器接口begin,end,rbegin和rend)
迭代器接口是获取容器元素指针的成员函数。`begin()`返回首元素的正向迭代器,`end()`返回末元素之后的位置。`rbegin()`和`rend()`提供反向迭代器,分别指向尾元素和首元素之前。C++11增加了const版本以供只读访问。示例代码展示了如何使用这些迭代器遍历字符串。
|
1天前
|
存储 编译器 C语言
【C++】string类的使用①(默认成员函数
本文介绍了C++ STL中的`string`类,它是用于方便地操作和管理字符串的类,替代了C语言中不便的字符数组操作。`string`基于`basic_string`模板,提供类似容器的接口,但针对字符串特性进行了优化。学习资源推荐[cplusplus.com](https://cplusplus.com/)。`string`类提供了多种构造函数,如无参构造、拷贝构造、字符填充构造等,以及析构函数和赋值运算符重载。示例代码展示了不同构造函数和赋值运算符的用法。
|
1天前
|
编译器 C++
【C++】类和对象⑤(static成员 | 友元 | 内部类 | 匿名对象)
📚 C++ 知识点概览:探索类的`static`成员、友元及应用🔍。
|
1天前
|
C++
C++基础知识(四:类的学习)
类指的就是对同一类对象,把所有的属性都封装起来,你也可以把类看成一个高级版的结构体。