首页 > c++primer第15章最后部分的类为什么不用make_shared而是用new初始化shared_ptr?

c++primer第15章最后部分的类为什么不用make_shared而是用new初始化shared_ptr?

如下所示,这本书前面告诉我尽量用make_shared初始化shared_ptr,这章中为何都是用new来初始化呢?难道是因为忘记更新第5版这章中的c++11的改动了吗?

class Query
{
    friend Query operator~(const Query&);
    friend Query operator|(const Query&, const Query&);
    friend Query operator&(const Query&, const Query&);
public:
    //! build a new WordQuery
    Query(const std::string& s) : q(new WordQuery(s))  //就是这里
    {
        std::cout << "Query::Query(const std::string& s) where s=" + s + "\n";
    }

    //! interface functions: call the corresponding Query_base operatopns
    QueryResult eval(const TextQuery& t) const
    {
        return q->eval(t);
    }
    std::string rep() const
    {
        std::cout << "Query::rep() \n";
        return q->rep();
    }

private:
    //! constructor only for friends
    Query(std::shared_ptr<Query_base> query) :
        q(query)
    {
        std::cout << "Query::Query(std::shared_ptr<Query_base> query)\n";
    }
    std::shared_ptr<Query_base> q;
};

刚好手边看到了勉力答下,希望能题主提供些参考。
make_shared比直接new一个raw pointer少申请一次内存,因为new一个ptr申请了一次内存,把这个ptr传给shared ptr时,shared ptr申请了一份空间来保存这个ptr。
这个并不是主要的问题,问题是如果当你用new来构造这个ptr时发生了异常,就会产生内存泄漏(没人帮你归还申请的堆内存)。如果你是用make_shared的话,即使构造失败,shared ptr的析构函数也能帮你擦好屁股。
详情可见Scott Meyers的Effective Modern C++ 中Item21


是为了动态绑定,make_shared<WordQuery>得到的是WordQuery类型shared指针,无法实现从Query_base到WordQuery的动态绑定。
q(std::make_shared<WordQuery>(s))报错的原因是初始化参数不对,把s改成WordQuery(s)可以编译通过,但是是静态绑定,无法实现设计目标。
顺便一提,即便用make_shared<Query_base>(WordQuery(s))实现指针也不行,会报错。即便派生类可以转换,派生类对象也会塌陷为基类对象,而丢弃派生类成员。依然无法实现程序设计目标。

【热门文章】
【热门文章】