2012-02-03 117 views
1

开始与代码:C++是堆栈还是堆分配?

#include <iostream> 
#include <string> 
#include <map> 

#include <boost/asio.hpp> 

typedef std::map<boost::asio::ip::address, int> Ip2Int; 
Ip2Int ip2int; 

void 
func1() 
{ 
    boost::asio::ip::address addr4 = boost::asio::ip::address::from_string("192.168.2.1"); 
    boost::asio::ip::address addr6 = boost::asio::ip::address::from_string("de::ad"); 

    ip2int.insert(std::pair<boost::asio::ip::address, int>(addr4, 1)); 
    ip2int.insert(std::pair<boost::asio::ip::address, int>(addr6, 2)); 
} 

int 
main() 
{ 
    func1(); 

    Ip2Int::iterator iter = ip2int.begin(); 
    do { 
     std::cout << iter->first << " -> " << iter->second << std::endl; 
    } while (++iter != ip2int.end()); 

    return 0; 
} 

我学习C++和上面的代码片段中我迷惑。在func1中,addr4和addr6的分配是堆栈分配(对吧?)。当func1存在时,它们应该消失(-ish,内存将保存该值,直到其他人使用它)。这原本让我觉得我对ip2int地图的散步可能会打印垃圾。尽管如此,我仍然无法做到这一点。

因为我还是新来的C++,我不排除我错过了一些东西。一个副本是否发生在我不知道的地方?我以为这对和地图插入调用都只是引用。这意味着他们可以在某个时候引用垃圾。

好吧,足够散漫。上面的代码是否有效,或者我是幸运的,没有其他东西可以用来存储addr4和addr6的内存?

在此先感谢任何和所有帮助

+0

我不知道增强,但一个简单的方法来检查是否堆栈或堆分配是使用调试器和放置断点(例如对构造函数)。你可能有一个堆栈分配的数据,但内部字段是堆分配的...... – 2012-02-03 17:00:13

+0

@BasileStarynkevitch你不能告诉它的堆或栈通过检查构造函数创建相同的构造函数在两种情况下都被调用。 – rerun 2012-02-03 17:06:58

+0

我的意思是在构造函数中,在运行时,在'gdb'调试器下面放置一个断点....然后,如果到达构造函数,调试器将能够显示其'this'隐式参数,如果该指针位于堆栈或堆上,则会有线索。 – 2012-02-03 17:19:31

回答

2

是的,当你做ip2int.insert < ..>(..)。

+0

非常感谢您的快速回答。 (我不能标记这个答案,但我会在5分钟内)你是怎么知道的?我一直在使用http://www.cplusplus.com/reference/stl/,但我没有发现任何提及插入内容的副本。 – user442585 2012-02-03 17:08:10

+0

@ user442585:任何时候“按值传递”(即没有通过引用或指针传递),然后复制。 (实际上,通过指针传递实际上只是按值传递一个指针 - 也就是说,接收者自己创建指针的副本。)因此,复制是C++的基础,而不是地图类特有的事情。 (这就是为什么它没有在STL参考中提到。) – 2012-02-03 17:24:03

+0

当您定义地图时,insert(..)需要一对,反过来为它的构造函数需要一个A和一个B.(即不是A&或B&)我敢肯定,如果你认为A是一个整数,它似乎不奇怪, int被复制。一个对象在这个意义上确实没有什么不同。我希望更清楚一点。 – user1130005 2012-02-03 17:25:40

2

此代码是有效的。将地址/ int对插入地图时,实际上是制作地址对象的副本。因此,名为“addr4”的堆栈本地地址对象不再存在,但它的一个副本(由地图所拥有)却不存在。这是您在函数返回时访问的副本。

1

插入到std::map中会生成该对象的副本。原始对象addr4addr6具有自动存储持续时间并在func1结束时被销毁,但其副本在ip2int(其具有静态存储持续时间)中愉快地生活,因此保证在程序执行期间有效。

0

Stl要求使用其映射为一个容器的对象是可复制构造的。所以听到的是ip2int在全球范围内是自动的,并且存在于程序的整个生命周期中。在Func1中,您正在创建两个自动装置并将其复制到地图中。在地图底层使用堆分配来包含这些值。当func1存在时,清除自动存储器中的内存并调用析构函数,但映射仍然存在,并且创建的副本仍然存在。