<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Soul Of Free Loop &#187; 析构</title>
	<atom:link href="https://zohead.com/archives/tag/destruct/feed" rel="self" type="application/rss+xml" />
	<link>https://zohead.com</link>
	<description>Uranus Zhou&#039;s Blog</description>
	<lastBuildDate>Sat, 19 Jul 2025 15:42:46 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.8</generator>
	<item>
		<title>vector的push_back拷贝构造和空间占用分析</title>
		<link>https://zohead.com/archives/vector-push-back-space-copy/</link>
		<comments>https://zohead.com/archives/vector-push-back-space-copy/#comments</comments>
		<pubDate>Fri, 04 May 2012 18:30:56 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[push_back]]></category>
		<category><![CDATA[STL]]></category>
		<category><![CDATA[拷贝]]></category>
		<category><![CDATA[构造]]></category>
		<category><![CDATA[析构]]></category>
		<category><![CDATA[编程]]></category>

		<guid isPermaLink="false">http://zohead.com/?p=104</guid>
		<description><![CDATA[本文同步自：https://zohead.com/archives/vector-push-back-space-copy/ 这两天在实际程序中使用 STL 的 vector push_back 类对象时出现问题，偶尔发现 vector 在 push_back 时的调用类对象的拷贝构造函数和析构函数有点特别，简单做下分析。 程序代码： 功能很简单，main 中定义一个 sss 类对象和对应的 vector，然后在循环中改类成员的值，并依次 push_back 到 vector 中，类的构造函数、析构函数、拷贝构造函数中都加了对应的打印输出。循环运行了5次，往 vector 中增加了5个类成员。 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>本文同步自：<a href="https://zohead.com/archives/vector-push-back-space-copy/" target="_blank">https://zohead.com/archives/vector-push-back-space-copy/</a></p>
<p>这两天在实际程序中使用 STL 的 vector push_back 类对象时出现问题，偶尔发现 vector 在 push_back 时的调用类对象的拷贝构造函数和析构函数有点特别，简单做下分析。</p>
<p><span style="color: #f00;"><strong>程序代码：</strong></span></p>
<p><pre class="brush: cpp; highlight: [11,16,22,36]; title: cat &gt; test.cpp; notranslate">
#include &lt;iostream&gt;
#include &lt;vector&gt;

using namespace std;

struct sss
{
public:
	explicit sss(int val) : value(val)
	{
		cout &lt;&lt; &quot;---init sss &quot; &lt;&lt; this &lt;&lt; &quot;, value:&quot; &lt;&lt; value &lt;&lt; endl;
	}

	sss(const sss&amp; org)
	{
		cout &lt;&lt; &quot;---copy &quot; &lt;&lt; &amp;org &lt;&lt; &quot; to &quot; &lt;&lt; this &lt;&lt; endl;
		value = org.value;
	}

	~sss()
	{
		cout &lt;&lt; &quot;---destory sss &quot; &lt;&lt; this &lt;&lt; &quot;, value:&quot; &lt;&lt; value &lt;&lt; endl;
	}
 
	int value;
};

int main(int argc, char ** argv)
{
	sss s_tmp(11);
	int i = 0;
	vector&lt;sss&gt; vvv;

	for (i = 0; i &lt; 5; i++) {
		s_tmp.value++;
		vvv.push_back(s_tmp);
		cout &lt;&lt; &quot;size: &quot; &lt;&lt; vvv.size() &lt;&lt; &quot;, capacity: &quot; &lt;&lt; vvv.capacity() &lt;&lt; endl;
	}

	return 0;
}
</pre>
</p>
<p>功能很简单，main 中定义一个 sss 类对象和对应的 vector，然后在循环中改类成员的值，并依次 push_back 到 vector 中，类的构造函数、析构函数、拷贝构造函数中都加了对应的打印输出。循环运行了5次，往 vector 中增加了5个类成员。</p>
<p>实际运行输出如下：</p>
<hr size="1" />
<p>---init sss 0x22ff20, value:11<br /> ---copy 0x22ff20 to 0x5d2a58<br /> size: 1, capacity: 1<br /> ---copy 0x5d2a58 to 0x5d2ad8<br /> ---copy 0x22ff20 to 0x5d2adc<br /> ---destory sss 0x5d2a58, value:12<br /> size: 2, capacity: 2<br /> ---copy 0x5d2ad8 to 0x5d2ae8<br /> ---copy 0x5d2adc to 0x5d2aec<br /> ---copy 0x22ff20 to 0x5d2af0<br /> ---destory sss 0x5d2ad8, value:12<br /> ---destory sss 0x5d2adc, value:13<br /> size: 3, capacity: 4<br /> ---copy 0x22ff20 to 0x5d2af4<br /> size: 4, capacity: 4<br /> ---copy 0x5d2ae8 to 0x5d2b00<br /> ---copy 0x5d2aec to 0x5d2b04<br /> ---copy 0x5d2af0 to 0x5d2b08<br /> ---copy 0x5d2af4 to 0x5d2b0c<br /> ---copy 0x22ff20 to 0x5d2b10<br /> ---destory sss 0x5d2ae8, value:12<br /> ---destory sss 0x5d2aec, value:13<br /> ---destory sss 0x5d2af0, value:14<br /> ---destory sss 0x5d2af4, value:15<br /> size: 5, capacity: 8<br /> ---destory sss 0x5d2b00, value:12<br /> ---destory sss 0x5d2b04, value:13<br /> ---destory sss 0x5d2b08, value:14<br /> ---destory sss 0x5d2b0c, value:15<br /> ---destory sss 0x5d2b10, value:16<br /> ---destory sss 0x22ff20, value:16</p>
<hr size="1" />
<p><span style="color: #f00;"><strong>结果分析：<br /> </strong></span></p>
<p>vector 每次调用 push_back 时都会拷贝一个新的参数指定的 sss 类对象，这会调用 sss 的拷贝构造函数，第一次的 copy 正常，而且 vector 的实际容量也由 0  变为 1。</p>
<p>第二次调用 push_back，通过输出会发现调用了两次拷贝构造函数，一次析构函数，原来 vector 此时判断容量不够，将容量扩大为原来的两倍，变为 2，并将原来的元素再次拷贝一份存放到新的内存空间，然后拷贝新加的类对象，最后再释放原来的元素。</p>
<p>第三次调用 push_back 时，vector 自动扩大为4，因此拷贝构造函数调用了3次，析构函数调用了2次，程序最终退出了时就析构了 5 次加本身的 sss 类对象一共 6 次。</p>
<p><span style="color: #f00;"><strong>参考：</strong></span></p>
<p>由此看来，vector 的 push_back 在发现空间不足时自动将空间以 2 的指数增长：0 -&gt; 1 -&gt; 2 -&gt; 4 -&gt; 8 -&gt; 16 -&gt; 32 ...</p>
<p>查找资料后得知，如此设计的主要目的是为了尽可能的减小时间复杂度；如果每次都按实际的大小来增加 vector 的空间，会造成时间复杂度很高，降低 push_back 的速度。</p>
<p>另外关于 push_back 为什么会执行拷贝构造函数，push_back 的原型为：</p>
<p><em><span style="color: #008000;">void push_back(const _Ty&amp; _Val)</span></em></p>
<p>参数是以引用方式传递，按说不会拷贝，但 push_back 实际实现中判断空间不足时是调用 insert 函数添加元素：</p>
<p><em><span style="color: #008000;">void push_back(const _Ty&amp; _Val)</span></em><br /> <em><span style="color: #008000;">{</span></em><br /> <em><span style="color: #008000;">   // insert element at end</span></em><br /> <em><span style="color: #008000;">   if (size() &lt; capacity())</span></em><br /> <em><span style="color: #008000;">   #if _HAS_ITERATOR_DEBUGGING</span></em><br /> <em><span style="color: #008000;">   {</span></em><br /> <em><span style="color: #008000;">      // room at end, construct it there</span></em><br /> <em><span style="color: #008000;">      _Orphan_range(_Mylast, _Mylast);</span></em><br /> <em><span style="color: #008000;">      _Mylast = _Ufill(_Mylast, 1, _Val);</span></em><br /> <em><span style="color: #008000;">   }</span></em><br /> <em><span style="color: #008000;">   #else /* _HAS_ITERATOR_DEBUGGING */</span></em><br /> <em><span style="color: #008000;">      _Mylast = _Ufill(_Mylast, 1, _Val);</span></em><br /> <em><span style="color: #008000;">   #endif /* _HAS_ITERATOR_DEBUGGING */</span></em><br /> <em><span style="color: #008000;">   else</span></em><br /> <em><span style="color: #008000;">      insert(end(), _Val);</span></em><br /> <em><span style="color: #008000;">}</span></em></p>
<p><span style="color: #f00;"><strong>更新：</strong></span></p>
<p>2012-05-10：</p>
<p>近期在 Visual Studio 2010 中发现 vector 的实际空间增加顺序为：1 - 2 - 3 - 4 - 6 - 9 - 13 - 19 - 28 - 42 - 63 - 94 - 141 - 211 ...，有空时再继续研究。</p>
<p>以上只是个人粗略分析，有任何问题欢迎指正，玩的开心咯 ^_^</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/vector-push-back-space-copy/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
