Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何返回C+中的列表+;_C++_List_Return - Fatal编程技术网

C++ 如何返回C+中的列表+;

C++ 如何返回C+中的列表+;,c++,list,return,C++,List,Return,假设我有一个列表类: class List { private: class Node{ public: int data; Node* next; public: virtual ~Node() { if (next != NULL)

假设我有一个列表类:

class List
{
    private:
        class Node{
            public:
                int data;
                Node* next;
            public:
                virtual ~Node()
                {
                    if (next != NULL)
                        delete next;
                }
        };

        Node* head;
    public:
        virtual ~List()
        {
            if (head != NULL)
            {
                delete head;
            }
        }
    public:
        void AddNode(int data);
        void DeleteNode(int data);
        //....  
};
现在我想实现一个函数,它将两个列表引用作为参数,并返回一个新创建的列表:

List SumTwoList(List& list_1, List& list_2)
{
    //here I create a new List list_3 and add some elements to it based on list_1 and list_2(add operation use dynamic allocation).

    //finally I want to return this list_3.
    return list_3;
}
我搞糊涂了。如何在
SumTwoList()中创建此
list\u 3
。如果我只是将其设为局部变量,当函数返回时,
list_3
的析构函数将释放添加到列表中的所有节点并销毁整个列表。但是,如果我执行动态分配来创建此
列表_3
,并返回指向它的指针,则用户有责任在使用后删除此列表


我不知道如何从这两个想法中进行选择,我很确定有更好的方法来解决这个问题。感谢您的建议。:-)

您将返回列表的副本。如果类
List
的复制构造函数和赋值运算符将被实现,这将实现您所期望的

class List
{
    private:
    //...
    public:
        List();
        List( const List& other);
        List& operator= ( const List& other);
    //...
};
但是,更好的选择可能是创建一个构造函数,该构造函数接受两个
List
s,并通过合并它们来构造一个新的构造函数(执行
SumTwoList
将执行的所有操作):


一个选项是返回指向新
列表的指针

List * SumTwoList(List& list_1, List& list_2)
{
    List * pResultList = new List;

    // Iterate over all elements of list_1 and add (append) them to pResultList
    // Iterate over all elements of list_2 and add (append) them to pResultList

    return pResultList;
}
但是,它有一个缺点,调用方必须记住删除返回的对象

相反,如果将
list_2
的元素附加到现有列表中,则可能更好地设计API

// Append contents of rhs to this. rhs stays as is
List::append( List const & rhs );
来电者可称之为

List list_1;
// work on list_1, such as add elements
List list_2;
// work on list_2, such as add elements

list_1.append( list_2 );
这接近于std::list::splice()
,但并非完全如此
splice()
将元素从
rhs
移动到
this
,但是
append()
复制元素

注意,你的析构函数有缺陷,它只删除了
头,后面的元素泄漏了

析构函数实现的草图

List::~List() {
    while( head ) {
        struct node * oldHead = head;
        head = head->next;
        delete oldHead;
    }
    head = NULL;
}

添加复制构造函数和赋值运算符(并修复析构函数):

“这需要实施”是您需要填写的内容,以使副本生效

那么这给你买了什么?首先,您现在可以按照您在问题中尝试使用的形式编写函数。也就是说,您可以安全地按值返回列表,而无需执行任何进一步的编码来动态分配或删除列表

List SumTwoList(List& list_1, List& list_2)
{
   List list_3;
   // do stuff to add data to list_3...
   //...
   //finally I want to return this list_3. 
   return list_3;
}
第二,假设我们要将一个列表复制到另一个列表。这可以通过使用“=”或简单的复制构造轻松完成

如果您不想复制,则通过使copy-ctor和assignment-op-private和unimplemented*关闭复制,否则复制将是使用您的类的程序员的一个选项,并且编译器也将在需要时进行复制

换句话说,如果复制实现正确,那么像这样的简单程序应该可以工作:

int main()
{
   List lis1;
   // Add some nodes to lis1...
   //...
   // Assume that lis1 now has nodes...complete the copying test
   List lis2(lis1);
   List lis3;
   lis3 = lis1;
}
上面的程序应该没有内存泄漏,甚至在main()返回时也不会崩溃。如果没有,则复制和/或销毁被破坏


*C++11允许您在定义函数时使用
delete
关键字,以比使用C++11之前的代码更简单的方式禁用复制构造函数和赋值运算符。

您正在返回一个副本。销毁的不是返回的副本。当然,这需要有一个正确的复制构造函数,而不仅仅是浅复制指针。@user3352668-您需要实现一个复制构造函数和赋值运算符。一旦您这样做并确认这两个函数可以工作,那么您的代码片段应该可以工作。顺便说一句,你的析构函数不起作用。@chris该副本是类列表的副本,不是每个与该列表关联的节点。这两个节点的头指针将指向同一个节点。当其中一个被销毁时,它将删除列表中的所有节点,因此类列表的新副本没有意义。@user3352668,这就是为什么您应该有一个复制构造函数,它不会像chris那样复制元素mentioned@adrin,这通常已经被(N)RVO和C++11if(N)中的移动语义所覆盖RVO不适用。-1:
但是,如果我执行动态分配以创建此列表并返回指向它的指针,则用户有责任在使用
后删除此列表。你的回答提供了什么?这个问题还没有陈述?@Paranaix:我知道,我在回答中已经提到了这个缺点。我还添加了另一种设计API的方法。@Arun我修改了List类。我想现在析构函数工作得很好。我现在要删除整个列表吗?@user3352668:对不起,这可能也不行。请看我更新的答案,我已经包括了析构函数的草图。@Arun我看到了你的答案。这样绝对可以消除一切。但是,在我的方法中,一旦列表删除第一个节点,第一个节点的第一个析构函数将删除第二个节点。。。所以我想最后每个节点都会被删除。此外,您的方法也适用于列表。如果我有一棵树呢?如果不使用父节点删除其子节点,则很难实现析构函数。我真的是一个初学者,所以我不确定我是否正确:)
List SumTwoList(List& list_1, List& list_2)
{
   List list_3;
   // do stuff to add data to list_3...
   //...
   //finally I want to return this list_3. 
   return list_3;
}
int main()
{
   List lis1;
   // Add some nodes to lis1...
   //...
   // Assume that lis1 now has nodes...complete the copying test
   List lis2(lis1);
   List lis3;
   lis3 = lis1;
}