更好地理解堆栈和列表
Posted
技术标签:
【中文标题】更好地理解堆栈和列表【英文标题】:better understand of heap stack and list 【发布时间】:2012-07-29 03:09:09 【问题描述】:有这个代码:
void set(list<Person*>* listP)
Person timmy = Person(10);
listP->push_back(&timmy);
int main()
list<Person*> listP;
set(&listP);
Person* timmy = listP.back();
如果我理解正确(请纠正我) timmy 是在堆栈上分配的,所以当我在 main 中使用它们时,我不能指望 timmy 的值。我对么?我需要像这样创建 timmy:
Person* timmy = new Person(10);
为了在堆上而不是在栈上创建,所以方法返回后不会被销毁?
谢谢
【问题讨论】:
【参考方案1】:void set(list<Person*>* listP)
Person timmy = Person(10); // create timmy on automatic storage (stack)
listP->push_back(&timmy); //push timmy's address
//timmy is destroyed. pushed address points to deallocated memory
是的,您需要使用Person* timmy = new Person(10);
在堆上分配。
void set(list<Person*>* listP)
Person *timmy = new Person(10); // timmy is a pointer now
listP->push_back(timmy); //push timmy's copy (copy of pointer)
//timmy (pointer) is destroyed, but not the memory it points to
还喜欢使用smart_pointers
,例如std::shared_ptr
、std::unique_ptr
或boost
智能指针。它将简化内存管理和编写exception-safe
代码
【讨论】:
@user1495181:你的理解是对的,但结论不一定,你可以用list<Person>
代替list<Person*>
。这样可以避免这些问题。
感谢指正。是的,它会避免但会复制新实例。
@user1495181:当然,问题是......?
返回值优化很可能会在这里发挥作用。不确定 rvo 的确切条件是什么,但到目前为止我从来没有遇到过这些条件。复制 100k 元素两次可能比执行 100k 堆分配更快,除非您的元素非常重。
@user1495181:看看这个问题:***.com/questions/4809120/…【参考方案2】:
您的假设是正确的,但如果您使用 list
或 Person
s 代替,您没有必须在“堆”上创建 timmy
:
void set(list<Person>& listP)
listP.push_back(Person(10));
极有可能不会在。在 C++11 中,即使没有省略复制,移动语义也可能发挥作用,并且复制代价高昂。push_back
(copy elision) 中制作额外的人员副本
【讨论】:
您是在谈论 RVO 吗?它不是只用于大物体吗?见下面的讨论。谢谢! @user1495181 RVO 是复制省略的子集,适用于按值返回。所以它不适用于这个例子。我推测 push_back 只会做一个构造,但实际上它会加上一个复制构造。但是在 C++11 中,临时的Person
会被移动复制。
@user1495181 我忘了说,RVO与返回对象的大小无关。
我测试看看 listP.push_back(Person(10)); dosnt 创建两个对象(在 c++11 中)并且确实如此。以上是关于更好地理解堆栈和列表的主要内容,如果未能解决你的问题,请参考以下文章