C/C++你必须知道的小知识(42)

62 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情


  1. move语义
//程序实例
#include <iostream>
using namespace std;
class first {
public:
    first() :num(new int(0)) {
        cout << "construct!" << endl;
    }
    //移动构造函数
    first(first &&d) :num(d.num) {
        d.num = NULL;
        cout << "first move construct!" << endl;
    }
public:    //这里应该是 private,使用 public 是为了更方便说明问题
    int *num;
};
class second {
public:
    second() :fir() {}
    //用 first 类的移动构造函数初始化 fir
    second(second && sec) :fir(move(sec.fir)) {
        cout << "second move construct" << endl;
    }
public:    //这里也应该是 private,使用 public 是为了更方便说明问题
    first fir;
};
int main() {
    second oth;
    second oth2 = move(oth);
    //cout << *oth.fir.num << endl;   //程序报运行时错误
    return 0;
}

/*    程序运行结果:
          construct!
        first move construct!
        second move construct
*/            

1.5.5 简述 C++ 中智能指针的特点

参考回答

  1. C++中的智能指针有4种,分别为:shared_ptr、unique_ptr、weak_ptr、auto_ptr,其中auto_ptr被C++11弃用。

  2. 为什么要使用智能指针:智能指针的作用是管理一个指针,因为存在申请的空间在函数结束时忘记释放,造成内存泄漏的情况。使用智能指针可以很大程度上避免这个问题,因为智能指针就是一个类,当超出了类的作用域时,类会自动调用析构函数,自动释放资源。

  3. 四种指针各自特性

    (1)auto_ptr

    ​ auto指针存在的问题是,两个智能指针同时指向一块内存,就会两次释放同一块资源,自然报错。

    (2)unique_ptr

    ​ unique指针规定一个智能指针独占一块内存资源。当两个智能指针同时指向一块内存,编译报错。

    ​ 实现原理: 将拷贝构造函数和赋值拷贝构造函数申明为private或delete。不允许拷贝构造函数和赋值操作符,但是支持移动构造函数,通过std:move把一个对象指针变成右值之后可以移动给另一个unique_ptr

    (3)shared_ptr

    ​ 共享指针可以实现多个智能指针指向相同对象,该对象和其相关资源会在引用为0时被销毁释放。

    ​ 实现原理: 有一个引用计数的指针类型变量,专门用于引用计数,使用拷贝构造函数和赋值拷贝构造函数时,引用计数加1,当引用计数为0时,释放资源。

注意: weak_ptr、shared_ptr存在一个问题,当两个shared_ptr指针相互引用时,那么这两个指针的引用计数不会下降为0,资源得不到释放。因此引入weak_ptr,weak_ptr是弱引用,weak_ptr的构造和析构不会引起引用计数的增加或减少。

答案解析

​ 无

1.5.6 weak_ptr 能不能知道对象计数为 0,为什么?

参考回答

​ 不能。

​ weak_ptr是一种不控制对象生命周期的智能指针,它指向一个shared_ptr管理的对象。进行该对象管理的是那个引用的shared_ptr。weak_ptr只是提供了对管理 对象的一个访问手段。weak_ptr设计的目的只是为了配合shared_ptr而引入的一种智能指针,配合shared_ptr工作,它只可以从一个shared_ptr或者另一个weak_ptr对象构造,它的构造和析构不会引起计数的增加或减少

答案解析

1.5.7 weak_ptr 如何解决 shared_ptr 的循环引用问题?

参考回答

​ 为了解决循环引用导致的内存泄漏,引入了弱指针weak_ptr,weak_ptr的构造函数不会修改引用计数的值,从而不会对对象的内存进行管理,其类似一个普通指针,但是不会指向引用计数的共享内存,但是可以检测到所管理的对象是否已经被释放,从而避免非法访问。

答案解析

​ 参见1.2.10

1.5.8 share_ptr 怎么知道跟它共享对象的指针释放了

参考回答

​ 多个shared_ptr对象可以同时托管一个指针,系统会维护一个托管计数。当无shared_ptr托管该指针时,delete该指针。

答案解析