实战c++中的智能指针unique_ptr系列-- unique_ptr的get()赋给普通指针后的崩溃(其实是生命周期惹的祸)

今天遇到一个错误,是关于unique_ptr的get方法的,忽略了。

之前博客是这样写get方法的:
其中bar是一个智能指针,p是一个普通指针:

p = bar.get(); 后,bar并非被释放,也就相当于指针p和智能指针bar共同管理一个对象,所以就*p做的一切,都会反应到bar指向的对象上。

那么来看今天的代码:

#include<iostream>
#include<memory>
class Widget {
public:
    Widget() { std::cout << "Widget::Widget()" << std::endl; }
    virtual ~Widget() { std::cout << "Widget::~Widget()" << std::endl; }
    virtual void draw() = 0;
};

class WindowsButton : public Widget {
public:
    WindowsButton() = default;
    ~WindowsButton() = default;
    void draw() { std::cout << "WindowsButton" << std::endl; }
};

int main() {
     std::unique_ptr<Widget> w = std::unique_ptr<Widget>(new WindowsButton());
     w.get()->draw();
     w->draw();
}

输出:
Widget::Widget()
WindowsButton
WindowsButton
Widget::~Widget()

就是使用w.get()和直接使用w是一样的效果!

现在就要玩点花样了:

#include<iostream>
#include<memory>
class Widget {
public:
    Widget() { std::cout << "Widget::Widget()" << std::endl; }
    virtual ~Widget() { std::cout << "Widget::~Widget()" << std::endl; }
    virtual void draw() = 0;
};

class WindowsButton : public Widget {
public:
    WindowsButton() = default;
    ~WindowsButton() = default;
    void draw() { std::cout << "WindowsButton" << std::endl; }
};

int main() {

    Widget* w = std::unique_ptr<Widget>(new WindowsButton()).get();
    w->draw();
}

上面的代码再执行w->draw()的时候会崩溃,why?

首先呢,这么写代码纯是吃饱撑的。
智能指针就是帮助我们管理内存的,为何又要赋值给普通指针呢?
好,即使你写了这样的代码,也是对变量生命周期不是很了解:

Widget* w = std::unique_ptr<Widget>(new WindowsButton()).get();

由于 unique_ptr 拥有对象,所以当unique_ptr 被摧毁的时候,它所指向的对象也会销毁,所以接下来的w指针指向的是一个已经销毁的对象,于是调用这个已经销毁对象的成员函数当然是错误的,导致崩溃。

个人觉得,尽量避免使用get方法,既然unique_ptr给我们提供了那么多的便利条件,我们就不应该铤而走险。

个人还觉得,尽量避免智能指针和普通指针的混合,那样容易非常的乱,导致内存泄露,导致崩溃。

你可能感兴趣的:(C++,unique-ptr)