C++不能从函数返回对象

C++不能从函数返回对象,c++,clipperlib,C++,Clipperlib,我尝试使用C++ clipple库,但是当我试图从一个函数中从clipple库返回一个对象时,它似乎变为null或者被某种方式改变了 这是我写的函数。唯一相关的行应该是最后3行 ClipperLib::PolyTree MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles) { // Make all of the triangles CW for (auto& triang

我尝试使用C++ clipple库,但是当我试图从一个函数中从clipple库返回一个对象时,它似乎变为null或者被某种方式改变了

这是我写的函数。唯一相关的行应该是最后3行

ClipperLib::PolyTree MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles)
{
    // Make all of the triangles CW
    for (auto& triangle : triangles)
    {
        triangle.makeClockwise();
    }
    // Set up the Clipper
    ClipperLib::Clipper clipper;
    // To take a union, add all the paths as "subject" paths
    for (auto& triangle : triangles)
    {
        ClipperLib::Path triContour(3);
        triContour[0] = convertGLMToClipperPoint(triangle.getVertex(0));
        triContour[1] = convertGLMToClipperPoint(triangle.getVertex(1));
        triContour[2] = convertGLMToClipperPoint(triangle.getVertex(2));
        clipper.AddPath(triContour, ClipperLib::PolyType::ptSubject, true);
    }
    // Now get the PolyTree representing the contours
    ClipperLib::PolyTree tree;
    clipper.Execute(ClipperLib::ClipType::ctUnion, tree);
    return tree;
}
当我调用clipper.execute时,它会将一些轮廓信息写入树结构中。它写的信息是正确的,我已经测试过它是正确的。但是,当我返回树时,它似乎没有复制任何内容,并且由该函数生成的PolyTree是空的

我确信图书馆没有什么问题,我只是在这里犯了一个初学者C++错误。希望有人知道它可能是什么

谢谢

编辑:以下是polytree的文档页面,仅供参考

编辑:我认为clipper库不是开源的,但它是开源的。这是密码

typedef std::vector< IntPoint > Path;
typedef std::vector< Path > Paths;
class PolyNode;
typedef std::vector< PolyNode* > PolyNodes;

class PolyNode 
{ 
public:
    PolyNode();
    Path Contour;
    PolyNodes Childs;
    PolyNode* Parent;
    PolyNode* GetNext() const;
    bool IsHole() const;
    bool IsOpen() const;
    int ChildCount() const;
private:
    unsigned Index; //node index in Parent.Childs
    bool m_IsOpen;
    JoinType m_jointype;
    EndType m_endtype;
    PolyNode* GetNextSiblingUp() const;
    void AddChild(PolyNode& child);
    friend class Clipper; //to access Index
    friend class ClipperOffset; 
};

class PolyTree: public PolyNode
{ 
public:
    ~PolyTree(){Clear();};
    PolyNode* GetFirst() const;
    void Clear();
    int Total() const;
private:
    PolyNodes AllNodes;
    friend class Clipper; //to access AllNodes
};

你的问题在三角形拓扑结构底部的第三行。您正在创建的树是在堆栈上创建的,并且仅在函数范围内


您应该动态分配内存并返回指向树的指针,或者使树对象成为类成员,以便在函数返回后它仍在作用域内。

您的问题在TriangleTopolytreeUnion底部的第三行。您正在创建的树是在堆栈上创建的,并且仅在函数范围内


您应该动态分配内存并返回指向树的指针,或者使树对象成为类成员,以便在函数返回后仍在作用域内。

在执行任何操作之前,请确保以下程序正常工作:

int main()
{
   PolyTree p1;
   // fill PolyTree with some values that make sense (please add code to do this)
   //...
   PolyTree p2 = p1; 
   PolyTree p3;
   p3 = p1;
}
这基本上就是我们想要测试的。如果您可以让这段代码正常工作,并添加相关的头和必要的初始化,那么您可以重新关注函数。如果上面的代码不起作用,那么这就是你的答案

您需要获得上面的代码以生成正确的复制语义,甚至非常重要的是,当main退出时,p1、p2和p3的销毁不会发生内存损坏


因此,您可以修复该类以安全地复制,或者忘记它,在有限的情况下使用您必须非常小心地处理的类,也就是说,您不能像现在这样可靠地返回该类的副本。

在执行任何操作之前,请确保以下程序正常工作:

int main()
{
   PolyTree p1;
   // fill PolyTree with some values that make sense (please add code to do this)
   //...
   PolyTree p2 = p1; 
   PolyTree p3;
   p3 = p1;
}
这基本上就是我们想要测试的。如果您可以让这段代码正常工作,并添加相关的头和必要的初始化,那么您可以重新关注函数。如果上面的代码不起作用,那么这就是你的答案

您需要获得上面的代码以生成正确的复制语义,甚至非常重要的是,当main退出时,p1、p2和p3的销毁不会发生内存损坏


因此,您可以修复该类以安全地复制,或者忘记它,在有限的情况下使用您必须非常小心地处理的类,也就是说,您不能像现在这样可靠地返回它的副本。

假设您不想修改显然设计糟糕的Clipper库,你可以像我在评论中建议的那样:

// Make sure to have this at the top of your header file:
#include <memory>

std::unique_ptr<ClipperLib::PolyTree> MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles)
{
    // Rest of your code...

    std::unique_ptr<ClipperLib::PolyTree> tree(new ClipperLib::PolyTree);
    clipper.Execute(ClipperLib::ClipType::ctUnion, *tree);
    return tree;
}
然后,调用函数时:

std::unique_ptr<ClipperLib::PolyTree> tree(yourMeshHandler.trianglesToPolyTreeUnion(/*...*/);

// make use of tree...

不过,如果有bug追踪器,我还是建议你开一张罚单,或者就这个问题与图书馆的作者联系。

如果你不想修改设计明显糟糕的Clipper图书馆,你可以按照我在评论中的建议做:

// Make sure to have this at the top of your header file:
#include <memory>

std::unique_ptr<ClipperLib::PolyTree> MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles)
{
    // Rest of your code...

    std::unique_ptr<ClipperLib::PolyTree> tree(new ClipperLib::PolyTree);
    clipper.Execute(ClipperLib::ClipType::ctUnion, *tree);
    return tree;
}
然后,调用函数时:

std::unique_ptr<ClipperLib::PolyTree> tree(yourMeshHandler.trianglesToPolyTreeUnion(/*...*/);

// make use of tree...

尽管如此,如果有bug追踪器,我还是建议你开一张罚单,或者就这个问题联系图书馆的作者。

记录在案,并在对这个问题的长时间讨论中综合所有的回答。 问题是:

返回的值是超出范围的局部变量。这将调用PolyTree析构函数 PolyTree包含一个PolyNode*指针向量。调用clipper.Execute时会分配这些。 但是PolyTree::Clear会删除节点。。。和Clear由析构函数调用。 因此,在函数内部,内容由Execute正确分配,当传递到外部时,在没有copy构造函数和operator=的情况下,调用局部变量的析构函数,清除节点,在函数外部接收的结果为空。 PolyTree::Clear的代码

void PolyTree::Clear() 
{
for (PolyNodes::size_type i = 0; i < AllNodes.size(); ++i)
      delete AllNodes[i];
    AllNodes.resize(0); 
    Childs.resize(0);
}
您可能应该遵循Execute模式,并将您的函数定义为:

void MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles,ClipperLib::PolyTree &tree) 

记录在案,并在对该问题的长时间讨论中综合所有回答。 问题是:

返回的值是超出范围的局部变量。这将调用PolyTree析构函数 PolyTree包含一个PolyNode*指针向量。调用clipper.Execute时会分配这些。 但是PolyTree::Clear会删除节点。。。和Clear由析构函数调用。 因此,在函数中,内容是由Execute正确分配的,当 在没有copy构造函数和operator=的情况下,当节点被清除时,调用局部变量的析构函数,在函数外部接收的结果为空。 PolyTree::Clear的代码

void PolyTree::Clear() 
{
for (PolyNodes::size_type i = 0; i < AllNodes.size(); ++i)
      delete AllNodes[i];
    AllNodes.resize(0); 
    Childs.resize(0);
}
您可能应该遵循Execute模式,并将您的函数定义为:

void MeshHandler::trianglesToPolyTreeUnion(std::vector<Triangle> triangles,ClipperLib::PolyTree &tree) 

这个问题已经有解决办法了吗?我正在处理同样的问题。 还是不走运。polytree仅输出内存地址


使用:qDebug时,是否已有解决此问题的方法?我正在处理同样的问题。 还是不走运。polytree仅输出内存地址



使用:qdebugh时,如果没有ClipperLib::PolyTree的定义,我们只能猜测。但是请注意,您是按值返回的,因此将涉及一些复制构造函数隐式或显式。@如果执行了复制省略,则jsantander不会执行,这在本例中很可能发生。RVO是C++中的少数例外之一,当程序的可观察行为可以随着优化而改变。不过,情况可能是这样。我想知道OP是否尝试摆弄优化标志。不相关,但您也应该通过const引用传递三角形:const std::vector&triangles@user3281410-请发布polytree定义。一旦你这样做了,你就会得到任何问题的答案。现在,我们不知道如果不实现用户定义的复制构造函数和赋值运算符,它是否可以安全复制。您可以粘贴未插入的代码,选择它,然后单击“代码”按钮,看起来像花括号{},它将整个选择缩进4个空格。注意标签。如果没有ClipperLib::PolyTree的定义,我们只能猜测。但是请注意,您是按值返回的,因此将涉及一些复制构造函数隐式或显式。@如果执行了复制省略,则jsantander不会执行,这在本例中很可能发生。RVO是C++中的少数例外之一,当程序的可观察行为可以随着优化而改变。不过,情况可能是这样。我想知道OP是否尝试摆弄优化标志。不相关,但您也应该通过const引用传递三角形:const std::vector&triangles@user3281410-请发布polytree定义。一旦你这样做了,你就会得到任何问题的答案。现在,我们不知道如果不实现用户定义的复制构造函数和赋值运算符,它是否可以安全复制。您可以粘贴未插入的代码,选择它,然后单击“代码”按钮,看起来像花括号{},它将整个选择缩进4个空格。注意标签。他们把凹痕弄脏了。不。这不是问题所在。如果对象具有正确的复制语义,则完全可以按值返回对象。否。这不是问题所在。如果对象具有正确的复制语义,则完全可以按值返回对象。但是请记住,PolyTree是一个库类,OP希望尽可能避免修改它。OK。但是这给了OP一个机会,让它能够准确地理解拥有一个安全可复制的对象需要什么。当然,我不是在批评你的答案,只是想提一提:谢谢保罗。我不理解C++的所有复杂性,但我认为这里的想法是测试拷贝分配和移动作业是否在这里工作?我会试试看,但是你希望编译器不允许编译这些语句吗?由于对象的析构函数异常,编译器无法自动生成对象的复制赋值或移动赋值?好吧,我试过了。它编译好了,似乎p2和p3都设置得很好。然而,当我从我使用的函数返回时,在局部变量p1、p2或p3的Clear命令中出现了访问冲突错误,我不知道该如何判断。看看jsantander的答案,我猜析构函数都试图多次删除相同的信息。嗯,但是请记住,PolyTree是一个库类,OP希望尽可能避免修改它。好的。但是这给了OP一个机会,让它能够准确地理解拥有一个安全可复制的对象需要什么。当然,我不是在批评你的答案,只是想提一提:谢谢保罗。我不理解C++的所有复杂性,但我认为这里的想法是测试拷贝分配和移动作业是否在这里工作?我会试试看,但是你希望编译器不允许编译这些语句吗?由于对象的析构函数异常,编译器无法自动生成对象的复制赋值或移动赋值?好吧,我试过了。它编译好了,似乎p2和p3都设置得很好。然而,当我从所使用的函数返回时,在局部变量p1、p2或p3的Clear命令中出现了访问冲突错误,我不知道该如何判断。查看jsantander的答案,
我猜析构函数都试图多次删除相同的信息。谢谢。我希望我能接受多个答案,但我已经承诺接受致命吉他在我的评论。谢谢。我希望我能接受多个答案,但我已经承诺在我的评论中接受致命吉他。我也同意致命吉他与作者联系。如果有的话,作者应该禁用复制和赋值,这样,如果试图复制,至少会生成编译器或链接器错误。我也同意与作者联系。如果有的话,作者应该禁用复制和赋值,这样,如果尝试复制,至少会生成编译器或链接器错误。这并不能提供问题的答案。您可以搜索类似的问题,或参考页面右侧的相关和链接问题以查找答案。如果您有一个相关但不同的问题,请提出一个新问题,并包括一个指向此问题的链接,以帮助提供上下文。请参阅:这并不是问题的答案。您可以搜索类似的问题,或参考页面右侧的相关和链接问题以查找答案。如果您有一个相关但不同的问题,请提出一个新问题,并包括一个指向此问题的链接,以帮助提供上下文。见: