C ++析构函数(带代码示例)

时间:2014-02-28 12:59:17

标签: c++ c++11

我刚刚从Java切换到C ++,到目前为止一切顺利。语言有点难,但我觉得好像在追赶。我有一个关于析构函数的问题,为此,我将提供我当前的代码,希望有人可以提供一些关于我应该如何进行的澄清。

我正在用OpenGL编写游戏并创建了三个类:Vector3D,Dimension3D和Cuboid。我的问题就像这样开始,我的长方体有一个Vector3D和Dimension3D的实例,你很快就会看到它。一旦标记为删除,我需要知道我的Cuboid类会发生什么(确切的例程)。或者更准确地说,如果我需要在发生此类事件时明确销毁Vector3D和Dimension3D实例。我希望我能充分阐述这个问题。

这是我的课程。

(Vector3D.cpp)

#include "Vector3D.h"

Vector3D::Vector3D(){
}

Vector3D::Vector3D( const float& x , const float& y , const float& z ){
    this->x = x;
    this->y = y;
    this->z = z;
}

Vector3D::~Vector3D(){
}

void Vector3D::setX( const float& x ){
    this->x = x;
}

void Vector3D::setY( const float& y ){
    this->y = y;
}

void Vector3D::setZ( const float& z ){
    this->z = z;
}

float Vector3D::getX(){
    return x;
}

float Vector3D::getY(){
    return y;
}

float Vector3D::getZ(){
    return z;
}

(Vector3D.h)

#ifndef NE3_Vector3D_H_
#define NE3_Vector3D_H_

class Vector3D{
public:
    Vector3D();
    Vector3D( const float& , const float& , const float& );
    ~Vector3D();
    void setX( const float& );
    void setY( const float& );
    void setZ( const float& );
    void setPosition( const float& , const float& , const float& );
    float getX();
    float getY();
    float getZ();
    float x;
    float y;
    float z;
private:
    // Private Members Go Here
};

#endif // NE3_Vector3D_H_

(Dimension3D.cpp)

#include "Dimension3D.h"

Dimension3D::Dimension3D(){
}

Dimension3D::Dimension3D( const float& width , const float& height , const float& depth ){
    this->width = width;
    this->height = height;
    this->depth = depth;
}

Dimension3D::~Dimension3D(){
}

void Dimension3D::setWidth( const float& width ){
    this->width = width;
}

void Dimension3D::setHeight( const float& height ){
    this->height = height;
}

void Dimension3D::setDepth( const float& depth ){
    this->depth = depth;
}

float Dimension3D::getWidth(){
    return width;
}

float Dimension3D::getHeight(){
    return height;
}

float Dimension3D::getDepth(){
    return depth;
}

(Dimension3D.h)

#ifndef NE3_Dimension3D_H_
#define NE3_Dimension3D_H_

class Dimension3D{
public:
    Dimension3D();
    Dimension3D( const float& , const float& , const float& );
    ~Dimension3D();
    void setWidth( const float& );
    void setHeight( const float& );
    void setDepth( const float& );
    void setSize( const float& , const float& , const float& );
    float getWidth();
    float getHeight();
    float getDepth();
    float width;
    float height;
    float depth;
private:
    // Private Members Go Here
};

#endif // NE3_Dimension3D_H_

最后,我的工作正在进行中Cuboid.cpp和Cuboid.h

(Cuboid.cpp)

#include "Cuboid.h"

Cuboid::Cuboid(){

}

Cuboid::Cuboid(const Vector3D& location, const Dimension3D& dimension){
    this->location = location;
    this->dimension = dimension;
}

Cuboid::~Cuboid(){
    // Do i do delete both location and dimension here?
}

void Cuboid::drawImmediate(){

}

void Cuboid::drawVBO(){

}

(Cuboid.h)

#ifndef NE3_CUBOID_H_
#define NE3_CUBOID_H_

#include "Vector3D.h"
#include "Dimension3D.h"

class Cuboid{

public:
    Cuboid();
    Cuboid( const Vector3D& , const Dimension3D& );
    ~Cuboid();
    void drawImmediate();
    void drawVBO();

    Vector3D location;
    Dimension3D dimension;
private:

};
#endif // NE3_CUBOID_H_

我在析构函数中的Cuboid.cpp中留下了评论。我想知道我是否应该删除那里的Vector3D和Dimension3D,以及一个显示最佳方法的示例。 IE:表达此功能的任何常见约定。

如果我的问题不充分,我将非常乐意提供进一步的澄清。此外,我确信还有其他类似的问题,但是,我需要在我自己的代码中看到它以完全掌握它。 (奇怪的学习风格),如果这变成了重复,请原谅我。

5 个答案:

答案 0 :(得分:5)

在这种特殊情况下,您不需要任何明确的销毁代码。

原因是您使用直接成员:

class Cuboid {
public:
    Vector3D location;
};

这意味着Vector3D对象嵌入进入Cuboid的内存,并与Cuboid一起自动分配和发布。

如果你有一个指向对象的指针作为成员(例如Vector3D *location)而不是成员本身,那将是另一种情况。在这种情况下,您还必须为location显式分配内存,并在析构函数中显式释放它。

答案 1 :(得分:4)

由于您刚刚开始使用C ++,您可以使用的初学者经验法则是明确删除您明确分配的内容。

由于您尚未自行分配Vector3D(例如通过new),因此您不应将其删除。

如果您的代码看起来像这样,那么情况会有所不同,

// Cuboid.cpp
Cuboid::Cuboid(){
    location = new Vector3d;
}

Cuboid::~Cuboid(){
    delete location; // now this is necessary
}

// Cuboid.hpp
class Cuboid {
private:
    Vector3D* location; // using a raw pointer here, this can be different for scoped/RAII pointer, unique_ptr
};

另外,考虑将成员设为私有,封装在C ++中与在Java中一样重要。


然后,随着C ++的进步,您将遇到RAII,一个稍微高级的主题,使规则无效,因为您将使用语言结构,或者您自己的作用域/ RAII类以确定的方式为您处理释放。例如,在以下情况中,

std::unique_ptr<Vector3D> location(new Vector3D);

您不需要自己解除分配location,当unique_pointer超出当前范围块时,或者当封闭对象(其中{)时,它将被C ++标准库自动释放。 {1}}是会员,将被取消分配。

答案 2 :(得分:2)

如果您在类Vector3D的构造函数中动态分配了Dimension3D对象和Cuboid对象,那么您需要在类Cuboid的析构函数中删除它们:

Cuboid::Cuboid(const Vector3D& location, const Dimension3D& dimension){
    this->location = new Vector3D(location);
    this->dimension = new Dimension3D(dimension);
}

Cuboid::~Cuboid(){
    delete location;
    delete dimension;
}

但是,由于代码中不是这种情况,因此您无需删除这些对象。

无论您使用Cuboid动态分配Cuboid* x = new Cuboid(...)对象,还是静态分配Cuboid x(...),这两个成员对象(locationdimension)都将隐式一旦调用类Cuboid的(空)析构函数就被销毁。

答案 3 :(得分:1)

不需要在其构造函数中删除Cuboid的位置和维度成员。当Cuboid实例被破坏时,它们的析构函数会被自动调用,因为您没有明确地管理它们的内存分配,即您在创建它们时没有使用“ new ”。

此外,根据您显示的代码,Vector3D和Dimension3D类都不需要在其析构函数中进行任何手动资源管理。基本上,如果您没有使用 new 为任何对象分配内存,通常不需要担心释放它们。

答案 4 :(得分:1)

不,需要取消分配成员locationdimension,因为它们是自动对象,其生命周期是自动控制的。当类Cuboid被销毁时,它们将自动被销毁。

事实上未定义的行为可以在{例如}上执行delete指向本地自动对象的指针。

作为最佳实践,您不应在C ++中使用delete(除非您知道自己在做什么)。如果你需要动态分配内存(并且标准库中的容器不能完成这项工作)那么你应该使用智能指针,如std::shared_ptr,它可以为你处理释放(see RAII)。