C ++函数中的复杂参数 - 指针,引用或......?

时间:2012-07-02 11:41:18

标签: c++ function pointers reference parameters

我有代码:

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,我不知道什么是好的mannier?与getStart / getEnd相同 - 它应该返回指针

Point3D * getStart(){return start;}

或只是变量

Point3D getStart()(return *start)

4 个答案:

答案 0 :(得分: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的好处。

亲切的问候, 托

答案 1 :(得分: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; }
};

答案 2 :(得分:1)

我认为正确的方法是:

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

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

甚至更好,智能指针。

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

答案 3 :(得分:1)

您的设计可能看起来效率较低,因为它的性质(每个元素都是孤立的)倾向于违反操作的位置。 复制在一起的东西可能比取消引用sparce的东西更有效。

因为你的向量只是...... 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有+ = - = +和 - 定义....