智能指针

使用智能指针需要引入 memory 头文件

unique_ptr

#include<iostream>
#include<string>
#include<memory>

class Entity {
public:
    Entity() {
        std::cout << "Created Entity!" << std::endl;
    }
    ~Entity() {
        std::cout << "Destoryed Entity!" << std::endl;
    }
    void Print() {}
};

int main() {
    {
        // std::unique_ptr<Entity> entity(new Entity());
        // 下面是更安全的写法
        // (如果构造函数抛出异常,不会得到悬空指针造成内存泄漏)
        std::unique_ptr<Entity> entity = std::make_unique<Entity>();
        entity->Print();
    }
    return 0;
}

unique_ptr指针会在离开作用域的时候自动销毁,这就是一个智能指针。

但请注意,unique_ptr指针不能复制的。假如说e1复制了e0,当e0离开作用域被销毁时,e1就指向了一片被销毁的空间,就出问题了。事实上你也不能复制,编译器没法编译的。

如果真的想复制,就要使用到另一个智能指针了,往下看。

shared_ptr

shared_ptr和unique_ptr一样的,都是智能指针,不过shared_ptr可以复制。先说说他是怎么解决unique_ptr无法复制的问题的:引用次数法。

大部分情况下都是引用次数法,还是上面那个例子,e1复制了e0,此时有两个指针指向了一片空间,引用次数为2,当e0离开作用域被销毁了,让引用次数减1。没少一个引用就减1,当引用次数为0时才释放内存。

用法和unique_ptr很像,上代码:

#include<iostream>
#include<string>
#include<memory>

class Entity {
public:
    Entity() {
        std::cout << "Created Entity!" << std::endl;
    }
    ~Entity() {
        std::cout << "Destoryed Entity!" << std::endl;
    }
    void Print() {}
};

int main() {
    {
        std::shared_ptr<Entity> e0;
        {
            std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();
            e0 = sharedEntity; // 可以复制
        } // 出了这个作用域,sharedEntity没了,但是还有e0,所以没析构
    }// 这里e0也没了,在这里调用了析构函数
    return 0;
}

weak_ptr

弱指针,可以和shared_ptr一起使用。当一个weak_ptr复制一个shared_ptr时,不会让shared_ptr的引用次数增加。他只在乎他要复制的那个指针是否有效,但是不去维持这个指针一直有效。上代码:

#include<iostream>
#include<string>
#include<memory>

class Entity {
public:
    Entity() {
        std::cout << "Created Entity!" << std::endl;
    }
    ~Entity() {
        std::cout << "Destoryed Entity!" << std::endl;
    }
    void Print() {}
};

int main() {
    {
        std::weak_ptr<Entity> e0;
        {
            std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();
            e0 = sharedEntity; // 可以复制
        } // 出了这个作用域,sharedEntity没了,weak_ptr e0没有增加引用次数,所以这里就析构了
    }
    return 0;
}
最后修改:2023 年 04 月 28 日
如果觉得我的文章对你有用,请随意赞赏