0

我有一个析构函数,它检查是否已分配指针,如果已分配,则将其删除:

ShadeRec::~ShadeRec(){

    cout << "before deleting ShadeRec" << endl;
    if(material){
        cout << material << endl;
        delete material;
        material = NULL;
    }
    cout << "after deleting ShadeRec" << endl;
}

第一个指针很好,然后在第二个指针上程序给了我错误。

我已经检查了couts 并且指针内部有一些东西,这是有道理的,因为它进入了 if 语句......那为什么它会给我错误?

构造函数:

ShadeRec::ShadeRec(World& world)
    :   hit(false),
        material(NULL),
        hitPoint(),
        localHitPoint(),
        normal(),
        ray(),
        depth(0),
        colour(0),
        t(0.0),
        w(world)
{}

ShadeRec::ShadeRec(const ShadeRec& sr)
    :   hit(sr.hit), 
        material(sr.material), 
        hitPoint(sr.hitPoint), 
        localHitPoint(sr.localHitPoint), 
        normal(sr.normal), 
        ray(sr.ray), 
        depth(sr.depth), 
        colour(sr.colour), 
        t(sr.t),
        w(sr.w)
{}

材料操作员=

Material& 
Material::operator= (const Material& rhs) {
    if (this == &rhs)
        return (*this);

    return (*this);
}

Matte 是 Material 的子对象:

Matte* matte1 = new Matte;

这两个:

Matte& operator= (const Matte& rhs);

virtual Material* clone(void) const;
4

2 回答 2

4

最有可能的是:

  • material如果是成员变量ShadeRec
  • 您的构造函数ShadeRec获取/设置指针
  • copy-ctor 没有定义,或者,如果是,只是复制指针,而不是创建它指向的对象的新实例。
  • 至少有两个实例ShadeRec,也许它被复制为参数或返回值。
  • 第一个 dtor 删除对象并将自己的指针设置为NULL
  • 第二个 dtor 在不同的对象上工作,它的指针仍然设置
  • 砰!

要使其可见,还要this在您的 dtor 中打印,您会看到它是ShadeRec.


编辑后:这是这一行:

material(sr.material),

它应该创建对象的副本,而不仅仅是复制普通指针。另一种选择,通常更可取,是使用 a std::shared_ptr(如果您可以使用 C++11,否则请查看boost::shared_ptr),但请注意, 的副本ShadeRec将共享相同的材质实例。

鉴于您到目前为止所显示的内容,请将上面的行从 copy-ctor 替换为

material(sr.material->clone()),

看看它是否有效。

于 2013-03-27T21:27:06.307 回答
2

问题

您没有定义深拷贝构造函数。当您复制ShadeRec对象时,指针会被复制,因为它们会导致两个类之间发生冲突。

像这样使用它时:

ShadeRec a;
ShadeRec b(a);

两个实例包含相同的地址,这意味着当第一个正确释放其指针时,第二个仍必须释放其指针(已被另一个释放)。

解决方案示例

这是一个正确的深拷贝构造函数的例子。考虑material是指向动态分配Material对象的指针,并且Material该类具有正确定义的复制构造函数:

ShadeRec::ShadeRec(const ShadeRec& sr)
    :   hit(sr.hit), 
        material(0), // <--- NULL 
        hitPoint(sr.hitPoint), 
        localHitPoint(sr.localHitPoint), 
        normal(sr.normal), 
        ray(sr.ray), 
        depth(sr.depth), 
        colour(sr.colour), 
        t(sr.t),
        w(sr.w)
{
    if (sr.material)
        material = new Material(*(sr.material));
}

这是一个如何编写正确的赋值运算符的示例:

Material& 
Material::operator= (const Material& rhs) {
    if (this != &rhs) {
        if (material)
            delete material;
        // make member per member assignments here
        material = new Material(*(rhs.material));
    }
    return (*this);
}

更多的

如果可以,您应该使用从 C++11std::shared_ptr开始在 STL 上实现的智能指针,或者在 C++11 之前,在 boost 库中以boost::shared_ptr.

于 2013-03-27T21:26:50.743 回答