如何在C++中返回列表
How to return a List in C++
假设我有一个List类:
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引用作为参数,并返回一个新创建的List:
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_3
。如果我只是让它成为一个局部变量,当函数返回时,list_3
的析构函数将释放添加到列表中的所有节点,并销毁整个列表。但是,如果我进行动态分配来创建此list_3
并返回指向它的指针,则用户有责任在使用后删除此列表。
我不知道如何从这两个想法中做出选择,我确信有一些更好的方法可以解决这个问题。谢谢你的建议。:-)
添加复制构造函数和赋值运算符(并修复析构函数):
class List
{
private:
typedef struct node{
int data;
struct node* next;
}NODE;
NODE* head;
public:
virtual ~List() // Please fix this, as others have mentioned!
{ }
List(const List& rhs)
{
// this needs to be implemented
}
List& operator = (const List& rhs)
{
// this needs to be implemented
}
//...
};
"这需要实现"是您需要填写的内容,以使副本发挥作用。
这能给你带来什么?首先,您现在可以按照您在问题中尝试的形式编写函数。也就是说,您可以安全地按值返回List,而无需进行任何进一步的编码来动态分配或删除列表。
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;
}
其次,假设我们要将一个列表复制到另一个列表。这可以使用"="或通过简单的复制构造轻松完成
如果你不想复制,那么通过将复制ctor和赋值设置为私有和未实现*来关闭复制,否则使用你的类的程序员可以选择复制,编译器也会在需要时进行复制。
换句话说,如果复制正确实现,那么像这样的简单程序应该可以工作:
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之前的代码更容易的方式禁用复制构造函数和赋值运算符。
一个选项是返回指向新List
的指针
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;
}
然而,它的缺点是调用者必须记住delete
返回的对象。
相反,如果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()
只是复制这些元素。
注意,您的析构函数有缺陷,它是delete'ing only the
头,后面的元素被泄露了。
析构函数实现的示意图
List::~List() {
while( head ) {
struct node * oldHead = head;
head = head->next;
delete oldHead;
}
head = NULL;
}
您将返回一个列表的副本。如果List
类的复制构造函数和赋值运算符将被实现,那么这将达到您所期望的效果。
class List
{
private:
//...
public:
List();
List( const List& other);
List& operator= ( const List& other);
//...
};
然而,也许更好的选择是创建一个构造函数,它占用两个List
,并通过合并它们来构造一个新的(像SumTwoList
那样完成所有这些):
class List
{
private:
//...
public:
List( const List& first, const List& second) { // similar to SumTwoList
}
//...
};
- C++:如何使函数只返回作为列表一部分的字符串
- 将大括号括起来的初始值设定项列表作为结构返回
- 从封装在对象中的函数 C++ 返回时为空的列表
- 如何在不销毁对象的情况下返回对象列表
- 什么更好?返回对象指针列表?或返回指向对象列表的指针?
- 如何优化代码以返回最接近给定整数的数字,但给定列表中不存在?
- 给定一个源文件,有没有办法要求 gcc 返回仅直接包含的头文件的列表?
- 当返回语句时,逗号运算符、大括号初始化列表和 std::unique_ptr 组合在一起
- 从非托管 C# DLL 返回列表/数组
- 在索引中插入节点:链接列表未正确返回列表
- C++列表函数返回列表
- 从 C++ 调用的 python 方法返回列表
- 如何返回列表成员 c++ 的空指针
- std::对中的C++返回列表
- 递归:按顺序遍历返回列表
- 返回列表元素的指针(如果具有相同的名称)
- 如何使用P/Invoke在C#中返回列表
- 当按值返回列表初始化的对象时,为什么不调用复制构造函数?
- 如何在C++中返回列表
- 返回列表前端 (C++) 的类型