实现对象列表时如何处理动态分配?
How to deal with dynamic allocation when implementing list of objects?
我必须实现一个如下所示的函数:
MyList * sum (MyList * l1, MyList * l2) {
MyList * newlist = new MyList();
//Adds two objects and place the result in a third new list
return newlist;
}
该函数采用两个列表并将每个对象的总和放入一个新列表中。 MyList
class 的节点带有指向 next
变量的指针,列表中的对象是用户定义的。
这让我开始思考 - 我应该如何处理对象和列表本身的内存动态分配?因为我必须为新列表的每个对象创建内存。
有没有什么办法可以不依赖动态分配,将对象总和的值放到新列表中?也许通过做这样的事情:
Object result(node1->content + node2->content);
Node->content = &result; // will this object be erased when the function ends?
而不是这个:
Node->content = new Object(node1->content + node2->content);
我应该如何处理与函数结束后将保存内存的变量相关的函数内部创建的新列表的生命周期?我可以在返回新列表时做这样的事情吗?
MyList & sum (MyList * l1, MyList * l2) {
//Create variable without allocating memory and return it's reference
}
简而言之,我的主要疑问是如何处理在函数内部创建的对象的生命周期,并将由其他对象持有。
Node->content = &result; // will this object be erased when the function ends?
是的,因为它是一个局部变量。一旦它的功能终止,result
的生命周期也会终止。
MyList & sum (MyList * l1, MyList * l2) {
//Create variable without allocating memory and return it's reference
}
这也会失败,原因与上述类似。
我建议你使用std::shared_ptr
or std::unique_ptr
. If you wish, read Differences between unique_ptr and shared_ptr。
Object result(node1->content + node2->content);
Node->content = &result; // will this object be erased when the function ends?
是的,如果result
是在函数体内用上面的语法创建的,它会在函数结束时销毁。
这就是为什么你应该使用 new
和动态分配的原因:这样,你的对象是在 heap 上创建的(而不是本地函数堆栈),它们 "survive" 创建它们的函数的末尾。您可以将返回的指针传递回调用者。当然,调用者必须正确 delete
返回的指针,否则最终会导致内存(或其他资源)泄漏。
在现代 C++ 中,您应该使用已经定义的 智能指针 classes,例如 std::shared_ptr
或 std::unique_ptr
,以及您的代码几乎不应该使用 explicit new
和 delete
(除非你正在开发一些定制的高度优化的数据结构,并且你需要对低级更细粒度的控制内存分配 - 即使在这种情况下,调用 new
和 delete
的显式代码也应该安全地包装在 RAII class 边界内。
但是,在我看来,您的代码更像是一个编程练习,这个练习的目的可能是学习使用显式 new
和 delete
进行动态内存分配。事实上,在生产质量代码中,您可以使用已经可用的标准链表 class 模板,而不是滚动您自己的列表 class,例如 std::list
.
我必须实现一个如下所示的函数:
MyList * sum (MyList * l1, MyList * l2) {
MyList * newlist = new MyList();
//Adds two objects and place the result in a third new list
return newlist;
}
该函数采用两个列表并将每个对象的总和放入一个新列表中。 MyList
class 的节点带有指向 next
变量的指针,列表中的对象是用户定义的。
这让我开始思考 - 我应该如何处理对象和列表本身的内存动态分配?因为我必须为新列表的每个对象创建内存。
有没有什么办法可以不依赖动态分配,将对象总和的值放到新列表中?也许通过做这样的事情:
Object result(node1->content + node2->content);
Node->content = &result; // will this object be erased when the function ends?
而不是这个:
Node->content = new Object(node1->content + node2->content);
我应该如何处理与函数结束后将保存内存的变量相关的函数内部创建的新列表的生命周期?我可以在返回新列表时做这样的事情吗?
MyList & sum (MyList * l1, MyList * l2) {
//Create variable without allocating memory and return it's reference
}
简而言之,我的主要疑问是如何处理在函数内部创建的对象的生命周期,并将由其他对象持有。
Node->content = &result; // will this object be erased when the function ends?
是的,因为它是一个局部变量。一旦它的功能终止,result
的生命周期也会终止。
MyList & sum (MyList * l1, MyList * l2) {
//Create variable without allocating memory and return it's reference
}
这也会失败,原因与上述类似。
我建议你使用std::shared_ptr
or std::unique_ptr
. If you wish, read Differences between unique_ptr and shared_ptr。
Object result(node1->content + node2->content); Node->content = &result; // will this object be erased when the function ends?
是的,如果result
是在函数体内用上面的语法创建的,它会在函数结束时销毁。
这就是为什么你应该使用 new
和动态分配的原因:这样,你的对象是在 heap 上创建的(而不是本地函数堆栈),它们 "survive" 创建它们的函数的末尾。您可以将返回的指针传递回调用者。当然,调用者必须正确 delete
返回的指针,否则最终会导致内存(或其他资源)泄漏。
在现代 C++ 中,您应该使用已经定义的 智能指针 classes,例如 std::shared_ptr
或 std::unique_ptr
,以及您的代码几乎不应该使用 explicit new
和 delete
(除非你正在开发一些定制的高度优化的数据结构,并且你需要对低级更细粒度的控制内存分配 - 即使在这种情况下,调用 new
和 delete
的显式代码也应该安全地包装在 RAII class 边界内。
但是,在我看来,您的代码更像是一个编程练习,这个练习的目的可能是学习使用显式 new
和 delete
进行动态内存分配。事实上,在生产质量代码中,您可以使用已经可用的标准链表 class 模板,而不是滚动您自己的列表 class,例如 std::list
.