C ++中std :: shared_ptr的数组如何工作

时间:2018-04-05 18:45:13

标签: c++ polymorphism smart-pointers

我是一名c ++初学者,学习智能指针和继承。我有一个基类Shape(抽象),作为派生类,我有Triangle,Isosceles和Equilateral。

我的想法是根据指向基类的类型为每个类打印适当的打印消息,我在main()中声明了如下所示。

#include <iostream>
#include <memory>

class Shape
{
public:
    virtual const void triangle()const = 0;
    virtual ~Shape(){ std::cout<<"Shape Deleted\n";  }
};

class Triangle: public Shape
{
public:
    virtual const void triangle()const override
    { std::cout<<"I am a triangle\n";   }
    virtual ~Triangle(){ std::cout<<"Triangle Deleted\n";   }
};

class Isosceles : public Triangle
{
public:
    virtual const void triangle()const override
    {   std::cout<<"I am an isosceles triangle\n";  }
    virtual ~Isosceles(){ std::cout<<"Isosceles Deleted\n";   }
};
class Equilateral: public Isosceles
{
public:
    virtual const void triangle()const override
    {   std::cout<<"I am an equilateral triangle\n";  }
    virtual ~Equilateral(){ std::cout<<"Equilateral Deleted\n";   }
};

当我使用传统方式使用new关键字创建指针对象时,所有类的析构函数都能完美地工作(下面给出了输出)。 main()是:

int main()
{
    Shape *Obj[3];
    Obj[0] = new Equilateral();
    Obj[1] = new Isosceles();
    Obj[2] = new Triangle();

    for(auto it: Obj)
        it->triangle();

    delete Obj[0];
    return 0;
}

The output is here

但是当我改为std::shared_ptr时,事情就不同了,我无法理解。 main()是:

int main()
{
    std::shared_ptr<Shape> obj[3];

    obj[0] = std::make_shared<Equilateral>();
    obj[1] = std::make_shared<Isosceles>();
    obj[2] = std::make_shared<Triangle>();

    for(auto it: obj)
        it->triangle();

    return 0;
}

The Output Now:

任何人都可以帮我搞清楚,为什么会这样? 可以提前感谢。

2 个答案:

答案 0 :(得分:1)

使用原始指针时,只会销毁第一个对象:

delete Obj[0];

并使其他2个泄漏,而当您使用std::shared_ptr正确清理所有3个对象时。这就是建议使用智能指针的确切原因。

答案 1 :(得分:0)

实际上你的第二个片段是正确的,输出完全符合预期。 您的第一个代码段有一个错误:您只是public string tables(string strFileName) { DataTable dt = null; try { recarrega = false; OleDbConnection conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.15.0;Data Source=" + strFileName + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES\";"); conn.Open(); dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null); conn.Close(); } catch (Exception a) { MessageBox.Show("15 - " + a.Message); try { recarrega = false; OleDbConnection conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.14.0;Data Source=" + strFileName + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES\";"); conn.Open(); dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null); conn.Close(); } catch (Exception b) { MessageBox.Show("14 - " + b.Message); try { recarrega = false; OleDbConnection conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.13.0;Data Source=" + strFileName + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES\";"); conn.Open(); dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null); conn.Close(); } catch (Exception c) { MessageBox.Show("13 - " + c.Message); try { recarrega = false; OleDbConnection conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + strFileName + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES\";"); conn.Open(); dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null); conn.Close(); } catch (Exception d) { MessageBox.Show("12 - " + d.Message); } } } } } 。那么delete obj[0];obj[1]怎么样?如果删除数组的所有成员,您将看到两个代码示例的输出之间的差异消失。 关于智能指针的好处是它们应该用于“即发即忘”的庄园。

最后,请仔细阅读你的那本书:在开始任何有关OOP的事情之前,你需要掌握构造和破坏的顺序。