我有代码:
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)
吗
答案 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有+ = - = +和 - 定义....