C++ C+中的复杂参数+;函数-指针、引用或。。。?

C++ C+中的复杂参数+;函数-指针、引用或。。。?,c++,function,pointers,reference,parameters,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;

我有密码:

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
现在,我有了代码:

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和endorLength设置为“我不知道什么是好的mannier”与getStart/getEnd相同-如果它返回指针

Point3D * getStart(){return start;}
Point3D getStart()(return *start)
或只是变量

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

我认为正确的方法是:

Vector3D(const Point3D& start, const Point3D& endOrLength, bool fromLength)
这样,所有权就不存在模糊性。此外,成员可能不应该是指针,否则可能会导致指针悬空,而应该是数据成员

或者更好,智能指针

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; }
};

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

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

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; }
};

首先,我不会像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有什么好处

亲切问候,,
Torsten

您的设计可能看起来效率较低,因为其本质(每个元素都是孤立的)倾向于违反操作的局部性。 在结合在一起的事物之间进行复制可能比在稀疏事物的解引用上进行操作要高效得多

既然你的向量是。。。。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有+=-=+和-定义的…

并使用Point3D getStart(){return start;}作为返回。或者将其设置为Point3D&如果您有一个较旧的编译器(或者甚至将其设置为const Point3D&当您希望确保point musn不被更改时),如果一些基本的东西(如点)可以通过值传递,而不是作为共享的存储库传递,那么应用程序将更加友好和简单,这将解决代码中的问题,但正如您所说,我的代码不是最好的方法。@PolGraphic我更新了我的答案,但我不确定你是否可以使用它。是的,就是它!谢谢:-)这是个好主意。很抱歉,我只能将一个响应标记为“已接受的应答”。幸运的是,我可以投票支持有用的anserw:-)如果使用c++11,我建议完全避免手动内存管理,而只使用
std::unique_ptr
。使复制/移动构造函数/析构函数/赋值操作更加简单(并且更容易获得正确的异常安全性)。唯一的例外是如果空间或运行时非常关键,但在这种情况下,可能最好避免在每个对象的基础上进行动态内存分配(例如,使用一个perallocated
数据池来代替
-对象)。@Grizzly:区别在于unique\u ptr可以采用“deleter”,因此,它需要添加更多内存来存储至少一个指向多态内部对象的运行时指针。如果没有提供deleter,好的实现可以避免这种情况。关于池,由于在任何时候都可能需要数据,而且不再需要数据,因此您必须管理池,让每个数据(或数据所有者)知道它们所属的池,并且您必须跟踪池中哪些数据正在使用或可重用。这可能会在全球范围内占用更多空间,事实上,最终会导致复制。。。(如下)@Grizzly:。。。在对操作系统执行操作时,“新建/删除”功能已被使用。内存池是一个好主意,但大多数CRT实现本身就已经有了它。@Emilogaravalia:(+可能的填充)并且调用可能是内联的)。考虑到仅对大对象进行动态分配的建议(以及动态内存分配的运行时/空间开销),这通常不应该是一个问题。关于池:如前所述,我只建议在运行时/空间约束非常严格的情况下使用(因此在这些情况下。。。