0

我有代码:

class Vector3D : public Vector{
protected:
    Point3D * start;
    Point3D * end;

public:
    ~Vector3D(){delete start; delete end;}
    Vector3D(Point3D * start, Point3D * endOrLength, bool fromLength){
        this->start = start;
        if(fromLength){
            this->end = new Vector3D(*start+*endOrLength); //the operator '+' is defined but I won't put it here,
            //because it's not important now
        }else
            this->end = endOrLength;
    }

    Point3D * getStart(){return start;}
    Point3D * getEnd(){return end;}
};

现在,我有代码:

Vector3D v(new Point3D(1,2,3), new Point3D(2,3,4), 0); //FIRST CREATION
Vector3D v(new Point3D(1,2,3), new Point3D(1,1,1), 1); //SECOND CREATION

第一次和第二次创建给了我相同的 Vector3D,但我认为它可能会产生内存泄漏。

是真的吗?以及如何解决?我想这样做并不优雅:

...
if(fromLength){
    this->end = new Vector3D(*start+*endOrLength);
    delete endOrLength;
}else
...

也许最好放 const Point3D &endOrLenght,我不知道有什么好方法?与 getStart/getEnd 相同 -它是否应该返回指针

Point3D * getStart(){return start;}

或者只是变量

Point3D getStart()(return *start)

?

4

4 回答 4

3

首先,我不会像 3d 点那样动态分配值对象。只需使用值,这可能会为您节省很多麻烦。其次,如果你有两种方法来构造你的向量,只需提供两个不同的构造函数:

class Vector3D {
public:
    Vector3D( const Point3D& s, const Point3D& e )
      : start( s )
      , end( e )
    {
    }

    Vector3D( const Point3D& s, const Vector3D& v )
      : start( s )
      , end( s + v )
    {
    }
}
private:
    Point3D start;
    Point3D end;
};

拥有一个根据函数参数执行两种不同操作的函数从调用方甚至难以理解。很难记住最后的 1 或 0 有什么用。

亲切的问候,托斯滕

于 2012-07-02T11:52:04.837 回答
2

您在此处编写代码可能不是处理此问题的最佳方式,而是直接解决您的问题:

Vector3D(Point3D * start, Point3D * endOrLength, bool fromLength){
    this->start = start;
    if(fromLength){
        this->end = new Vector3D(*start+*endOrLength); // I think you mean to use endOrLength here and not length.
        if (endOrLength)
            delete endOrLength;
    }else
        this->end = endOrLength;
}

我认为解决您的问题的更好方法是使用智能指针,最好的解决方案是查看是否可以替换指针。

class Vector3D : public Vector
{
protected:
    Point3D _start;
    Point3D _end;

public:
    Vector3D(const Point3D& start, const Point3D& endOrLength, bool fromLength) :
    _start(start),
    _end(fromLength ? Vector3D(start + endOrLength) : endOrLength)
    {
    }

    const Point3D& getStart() const { return _start; }
    const Point3D& getEnd() const { return _end; }
};
于 2012-07-02T11:47:28.063 回答
1

我认为正确的方法是:

Vector3D(const Point3D& start, const Point3D& endOrLength, bool fromLength)

这样,所有权就没有歧义。此外,成员可能不应该是指针,否则这可能会导致悬空指针,而是数据成员。

或者更好的是智能指针。

如果使用智能指针,则可以从 get 函数返回智能指针。

于 2012-07-02T11:44:00.597 回答
1

您的设计可能看起来效率较低,因为它的本质(每个元素都是孤立的)倾向于违反操作的局部性。在在一起的事物之间进行复制可能比对稀有事物的取消引用操作更有效。

而且由于您的向量只是 .... 2*3 数字,因此请避免动态内存的所有复杂性,而只需使用正常值语义。

如果您到达更大尺寸的对象(例如 3d 投影矩阵,可能有多达 16 个系数),请考虑仅将动态内存处理到类内部的想法。在你的情况下,这可以是

class Vector3d
{
    struct data
    { Point3d start, end; };

    Vector3d() :dp(new data) {}
    Vector3d(const Point3d& a, const Point3d& b) :p(new data({a,b})) {}

    Vector3d(const Vector3d& a) :p(new data(*a.p)) {}
    Vector3d(Vector3d&& a) :p(a.p) { a.p=nullptr; }
    Vector3d& operator=(Vector3d a) { delete p; p=a.p; a.p=nullptr; return *this; }
    ~Vector3d() { delete p; }

    const Poin3d& start() const { return p->start; }
    const Poin3d& end() const { return p->end; }

    //here define the compound assignment arithmetic
    //e.g.:
    Vector3d& operator+=(const Point3d& ofst)
    { p->start += ofst; p->end += ofst; return *this; }

    //alternativelly you can define assign in term of arithmetic
    Vector3d& operator-=(const Poinr3d& ofst)
    { *this = *this - ofst; return *this; } //will create a temporary that will be moved

private:
    data* p;
};

//and here define the point3d, vectopr3d and mixed arithmetic
//e.g.:
Vector3d operator+(Vector3d a, const Point3d& s)
{ a += s; return std::move(a); }

//this follow the alternative example
Vector3d operator-(const Vecotr3d& a, const Point3d& s)
{ return Vector3d(a.start()-s, a.end()-s); }

通过这种方式,动态内存的所有管理以及副本的生成(在需要时)或移动(在可能的情况下)都留在了类中。其他一切都适用于标准值语义。

注意:我假设 Poin3d 有 += -= + 和 - 定义....

于 2012-07-02T12:15:26.007 回答