C++向量在递归函数中丢失数据

Posted

技术标签:

【中文标题】C++向量在递归函数中丢失数据【英文标题】:C++ vector loses data in recursive function 【发布时间】:2012-02-17 15:55:33 【问题描述】:

我对 C++ 非常陌生,我正在尝试实现一个 TriangleDynamic 对象,该对象可以使用名为 splitTriangleProject 的函数递归地拆分自身。它将自己拆分为四个较小的 TriangleDynamic 对象(并将新三角形的顶点投影到具有给定半径和原点的球体上,但我相信这不是重点),将新创建的三角形推入一个向量中,该向量是原始对象的成员数据。矢量成员数据称为 subTriangles。然后每个 subTriangle 调用 splitTriangleProject 函数,直到出现某个“级别”的拆分。

我遇到的问题是,只有第一级拆分实际上正确地推送到 subTriangles 向量。我确信问题与超出范围的向量有关,或者可能是 TriangleDynamic 超出范围。我想有一些带有指针的解决方案。如果有人可以提供帮助,将不胜感激。

这是我的 TriangleDynamic 声明:

class TriangleDynamic

public:
    TriangleDynamic(const Point &P1, const Point &P2, const Point &P3);
    TriangleDynamic();
    ~TriangleDynamic()
    void printTriangle();
    void splitTriangleProject( int currentLevel, int maxLevel, const Point &org, double radius);
    void init();
    bool operator<(const TriangleDynamic&);
    bool operator>(const TriangleDynamic&);
    Line edge1;
    Line edge2;
    Line edge3;

    Point p1;
    Point p2;
    Point p3;

    Vect normal;

    bool lowestLevel;

    vector<TriangleDynamic> subTriangles;
    static int numTriangles;
    int triangleId;
;

int TriangleDynamic::numTriangles = 0;

和构造函数:

// constructor for the TriangleDynamic object
TriangleDynamic::TriangleDynamic(const Point &P1, const Point &P2, const Point &P3)

    p1 = P1;
    p2 = P2;
    p3 = P3;
    init();


TriangleDynamic::TriangleDynamic()

    p1 = Point(0,0,0);
    p2 = Point(0,0,1);
    p3 = Point(0,1,0);
    init();


void TriangleDynamic::init()

    edge1 = Line(p1,p2);
    edge2 = Line(p2,p3);
    edge3 = Line(p3,p1);

    Vect U = p2.minus( p1);
    Vect V = p3.minus(p1);

    normal = U.cross(V);

    lowestLevel = true;
    triangleId = numTriangles + 1;
    numTriangles = triangleId;

这是我的 splitTriangleProject 函数:

void TriangleDynamic::splitTriangleProject(int currentLevel, int maxLevel, const Point &org, double radius)

    if ( currentLevel < maxLevel)
    
        lowestLevel = false;
        Point worldOrigin = Point(0,0,0);
        double edge1MidMag = (edge1.midpoint - org).distance(worldOrigin) ;
        double edge2MidMag = (edge2.midpoint - org).distance(worldOrigin) ;
        double edge3MidMag = (edge3.midpoint - org).distance(worldOrigin) ;

        Point newEdge1Mid = (((edge1.midpoint) * radius )/ edge1MidMag) + org;
        Point newEdge2Mid = (((edge2.midpoint) * radius )/ edge2MidMag) + org;
        Point newEdge3Mid = (((edge3.midpoint) * radius )/ edge3MidMag) + org;

        TriangleDynamic t1(p1 , newEdge1Mid , newEdge3Mid);
        subTriangles.push_back(t1);

        TriangleDynamic t2(newEdge1Mid, p2, newEdge2Mid);
        subTriangles.push_back(t2);

        TriangleDynamic t3(newEdge3Mid, newEdge2Mid, p3);
        subTriangles.push_back(t3);

        TriangleDynamic t4(newEdge1Mid, newEdge2Mid, newEdge3Mid);
        subTriangles.push_back(t4);

        t1.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);
        t2.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);
        t3.splitTriangleProject( currentLevel + 1, maxLevel, org, radius); 
        t4.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);
    

这是一个在完成后递归打印三角形动态的函数:

void TriangleDynamic::printTriangle()

    cout<< "p1";
    p1.printPoint();
    cout << "\np2";
    p2.printPoint();
    cout << "\np3";
    p3.printPoint();
    cout << "\n\n";

    if(!lowestLevel)
    
        int ctr;
        for (ctr=0; ctr<=subTriangles.size()-1; ctr++)
        
            cout << "subTriangle\n";
            subTriangles[ctr].printTriangle();
        
    

这是我在 main 中的称呼:

int main()

    TriangleDynamic t = TriangleDynamic();
    t.splitTriangleProject(0,3,Point(), 1);
    t.printTriangle();
    cin.get();
    return 0;

我认为我在这一点上发布的太多了。任何帮助表示赞赏,在此先感谢。

【问题讨论】:

【参考方案1】:

问题就在这里

    TriangleDynamic t1(p1 , newEdge1Mid , newEdge3Mid);
    subTriangles.push_back(t1);

    TriangleDynamic t2(newEdge1Mid, p2, newEdge2Mid);
    subTriangles.push_back(t2);

    TriangleDynamic t3(newEdge3Mid, newEdge2Mid, p3);
    subTriangles.push_back(t3);

    TriangleDynamic t4(newEdge1Mid, newEdge2Mid, newEdge3Mid);
    subTriangles.push_back(t4);

    t1.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);
    t2.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);
    t3.splitTriangleProject( currentLevel + 1, maxLevel, org, radius); 
    t4.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);

请注意在调用 splitTrangleProject 之前如何将三角形的副本推送到 subTriangles 向量中。

因此,向量中的三角形没有调用 splitTriangleProject。

将推回移到代码的末尾,它应该可以工作。

    TriangleDynamic t1(p1 , newEdge1Mid , newEdge3Mid);


    TriangleDynamic t2(newEdge1Mid, p2, newEdge2Mid);


    TriangleDynamic t3(newEdge3Mid, newEdge2Mid, p3);


    TriangleDynamic t4(newEdge1Mid, newEdge2Mid, newEdge3Mid);


    t1.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);
    t2.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);
    t3.splitTriangleProject( currentLevel + 1, maxLevel, org, radius); 
    t4.splitTriangleProject( currentLevel + 1, maxLevel, org, radius);

    subTriangles.push_back(t3);
    subTriangles.push_back(t2);
    subTriangles.push_back(t1);
    subTriangles.push_back(t4);

(另外,另一方面,如果此代码开始变慢,则可以使用 C++11 std::move 大大加快速度。除非必须,否则不要进入指针。)

【讨论】:

就是这么简单!谢谢你。它有效,但我也会尝试你的其他建议。 既然你在这里很好地回答了我的问题,我希望你能看看我的新困境。没有压力,但这里是:link【参考方案2】:

在 splitTriangleProject() 中计算出子三角形后,您需要检索它们并添加到类自己的列表(subTriangles)中。 像这样:

void splitTriangleProject( int currentLevel, int maxLevel, const Point &org, double radius)

// your code above

subTriangles.insert(subTriangles.begin(), t1.subTriangles.begin(), t1.subTriangles.end());
subTriangles.insert(subTriangles.begin(), t2.subTriangles.begin(), t2.subTriangles.end());
subTriangles.insert(subTriangles.begin(), t3.subTriangles.begin(), t3.subTriangles.end());
subTriangles.insert(subTriangles.begin(), t4.subTriangles.begin(), t4.subTriangles.end());


然后你需要添加一个额外的访问方法“const vector& getSubTriangles()”。 (现在您似乎将所有成员变量共享为公共,这不是一个好习惯)

【讨论】:

谢谢!是的,在努力让事情发挥作用的过程中,我把所有事情都公开了。一点都不好。【参考方案3】:

当你 push_back 一个三角形到向量中时,它会推入一个三角形的副本。然后你在 t1 到 t4 上递归,但是这个递归不会影响已经推入向量中的内容,因为它是一个副本。

【讨论】:

以上是关于C++向量在递归函数中丢失数据的主要内容,如果未能解决你的问题,请参考以下文章

C++递归解析树思路

是否可以让递归函数调用 C++ 中的另一个函数?

使用递归的 C++ 中的骑士之旅

递归 JavaScript 函数正在丢失返回值

如何在 C++ 中的类中递归调用函数方法?

递归向量返回